将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);
}
这是正确的方法吗?如果没有,请建议一个。
答案 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)
有时当索引过期时,您的内容树中可能不再存在返回的搜索项,因此重建索引并再次尝试搜索,
您可以应用于搜索的一些增强功能: