在Sitecore中进行简单搜索

时间:2016-10-17 15:29:28

标签: sitecore sitecore-mvc sitecore8.2

将Sitecore 8.2与MVC一起使用。
我试图在MVC视图中实现搜索功能。 (使用文本框和提交按钮)

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

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

此方法无效,因为它返回null Item。

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 个答案:

答案 0 :(得分:7)

路径

避免查询这样的路径:

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()

空项目

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

搜索模板字段

这只是搜索项目名称。您只能在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);

将在项目的任何字段中找到searchterm存在的结果。

答案 1 :(得分:1)

首先,你检查过&#34;查询&#34;包含任何结果? 我建议执行以下搜索查询:

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());

答案 2 :(得分:1)

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

首先创建自己的Sitecore索引,而不是简单地使用默认的主索引或Web索引。如果这样做,您可以保护以下代码行.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()检索项目。也许您可以在尝试检索项目时向我们提供该属性的值。

答案 3 :(得分:1)

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

您可以应用于搜索的一些增强功能:

  • 正如基督徒回答中所提到的,您可以只为您的图书树创建索引,这意味着将索引的根目录设置为图书根项目.Web索引通常用于完整网站内容搜索。
  • 而不是获取所有书籍项目,然后通过所有项目;你可以使用谓词;即使在创建新索引之后,也只使用谓词来获取所需的项目。
  • 此外,如果您的网站是多语言的,请添加谓词来过滤所需的语言,否则您将获得同一项目的多个版本。