4

将 Sitecore 8.2 与 MVC 结合使用。
我正在尝试在 MVC 视图中实现搜索功能。(带有文本框和提交按钮)

内容树中有一个名为的文件夹,Books其中包含项目列表。每个项目都有这些字段 - 标题、作者、价格

当用户搜索一个词时,将检查它是否与该项目的 3 个字段中的任何一个匹配并返回结果。

此方法不起作用,因为它返回 null 项。

public PartialViewResult GetSearchBooks(string txtSearch)
 {

   string index = string.Format("sitecore_{0}_index", Sitecore.Context.Database.Name);
   List<SearchResultItem> query;
   List<Item> matches = new List<Item>();

   using (var context = ContentSearchManager.GetIndex(index).CreateSearchContext())
   {
     query = context.GetQueryable<SearchResultItem>()
             .Where(p => p.Path.StartsWith("/sitecore/content/Book")).ToList();
   }

   foreach(SearchResultItem sritem in query)
   {
     Item item = sritem.GetItem(); //item is null here

     if(item.Fields["Title"].Value.Contains(txtSearch) ||
        item.Fields["Title"].Value.Contains(txtSearch) ||
        item.Fields["Title"].Value.Contains(txtSearch))
        matches.Add(item);
   }

   return(matches);
}

是不是正确的做法。如果没有,请推荐一个。

4

4 回答 4

9

路径

避免像这样查询路径:

context.GetQueryable<SearchResultItem>()
         .Where(p => p.Path.StartsWith("/sitecore/content/Book"));

而是使用

context.GetQueryable<SearchResultItem>()
             .Where(p => p.Paths.Contains(idOfBookFolderItem));

有关原因的更多信息,请参阅http://blog.paulgeorge.co.uk/2015/05/29/sitecore-contentsearch-api-filtering-search-on-folder-path/

方法

您需要一次性将整个查询交给搜索 API。

        List<SearchResultItem> matches;

        using (var context = ContentSearchManager.GetIndex(indexName).CreateSearchContext())
        {
            var predicate = PredicateBuilder.True<SearchResultItem>();

            // must have this (.and)
            predicate = predicate.And(p => p.Paths.Contains(bookFolderItem.ID));

            // must have this (.and)
            predicate = predicate.And(p => p.Name == searchTerm);

            matches = context.GetQueryable<SearchResultItem>().Where(predicate).ToList();
        }

这将返回 SearchResultItems 而不是 Items。如果您需要该项目,只需调用 GetItem。

Matches[i].GetItem()

空项目

这可能表明您的索引与数据库不同步。尝试从控制面板重新建立索引,或者在网络数据库的情况下,重新发布预期的内容。

搜索模板字段

这只是搜索项目名称。您只能在 SearchResultItem 类中指定通用字段。如果要搜索项目的特定字段,可以从 SearchResultItem 继承并添加这些字段。

public class BookSearchResultItem : SearchResultItem
{
    [IndexField("Book Title")]
    public string BookTitle { get; set; }

    [IndexField("Book Author")]
    public string BookAuthor { get; set; }
}

然后,您可以将其传递到查询中并在这些字段上进行搜索

        List<BookSearchResultItem> matches;

        using (var context = ContentSearchManager.GetIndex(indexName).CreateSearchContext())
        {
            var predicate = PredicateBuilder.True<BookSearchResultItem>();

            // must have this (.and)
            predicate = predicate.And(p => p.Paths.Contains(bookFolderItem.ID));

            // must have this (.and)
            predicate = predicate.And(
                PredicateBuilder.False<BookSearchResultItem>() // in any of these fields
                .Or(p => p.BookTitle == searchTerm) 
                .Or(p => p.BookAuthor == searchTerm)
                .Or(p => p.Name == searchTerm)); 

            matches = context.GetQueryable<BookSearchResultItem>().Where(predicate).ToList();
        }

搜索所有“内容”

如果您发现必须指定显式字段是不必要的麻烦,或者您要在具有不同字段的不同模板中执行搜索,您可以改用特殊的计算“内容”字段,它将项目中的所有文本数据组合到一个索引字段中. 因此,而不是执行此操作的原始查询

predicate = predicate.And(p => p.Name == searchTerm);

你可以改为使用

predicate = predicate.And(p => p.Content == searchTerm);

它将在项目的任何字段中找到搜索词存在的结果。

于 2016-10-26T16:23:56.853 回答
1

我不建议使用这种方法。让我解释一下为什么,或者你可以做得更好。

首先创建您自己的 Sitecore 索引,不要简单地使用默认的主索引或网络索引。如果这样做,您可以保护以下代码行.Where(p => p.Path.StartsWith("/sitecore/content/Book")).ToList();,因为在自定义索引中您可以简单地限制抓取的内容。

其次,您永远不应该从搜索结果中访问 Sitecore 项目。原因是性能。Item item = sritem.GetItem();您使用搜索,因为它是访问大量数据的一种高效方式。当您现在从数据库中访问 Sitecore 项目的每个结果时,您将失去使用搜索的好处。

您应该简单地使用结果类型,在您的情况下是基本的SearchResultItem. 在过滤结束时,您应该调用类似var results = query.GetResults();而不是直接访问项目。

在这里,我找到了一个简单的站点核心搜索示例,具有自定义索引并且无需直接访问项目,也许这对您有所帮助。

http://www.mattburkedev.com/sitecore-7-contentsearch-tips/

现在到你的问题。您是否调试了搜索并查看了 的其余字段sritem?都填满了吗?如果我没记错的话,有一个存储 itemId 的属性,可以使用GetItem(). 也许您可以在尝试检索项目时向我们提供属性的值。

于 2016-10-17T18:41:13.277 回答
1

首先,您检查“查询”是否包含任何结果?我建议执行以下搜索查询:

query = context.GetQueryable<SearchResultItem>()
         .Where(p => p.TemplateId == yourBookItemTemplateID &&  
                     (p.Fields["Title"].Value.Contains(txtSearch) ||
                      p.Fields["Author"].Value.Contains(txtSearch) || 
                      p.Fields["Price"].Value.Contains(txtSearch));

return query.Select(x => x.GetItem());
于 2016-10-17T15:54:49.717 回答
1

有时当索引过期时,返回的搜索项可能不再存在于您的内容树中,因此请重建索引并再次尝试搜索,

您可以应用于搜索的几个增强功能:

  • 正如 Christian answer 中提到的,您可以仅为您的 Books 树创建索引,这意味着将索引的根设置为 Books 根项。Web 索引通常用于完整的站点内容搜索。
  • 不是获取所有书籍项目,而是查看所有项目;您可以改用谓词;即使在您创建新索引之后,也只能使用谓词来获取所需的项目。
  • 此外,如果您的网站是多语言的,请添加谓词来过滤所需的语言,否则您将获得同一项目的多个版本。
于 2016-10-17T19:32:22.547 回答