我的sitecore pages / lucene文档包含以下字段:
我正在创建这些搜索并具有以下要求:
这就是我所拥有的:
public static Expression<Func<T, bool>> GetSearchTermPredicate<T>(string searchTerm)
where T : ISearchableItem
{
var actualPhrasePredicate = PredicateBuilder.True<T>()
.Or(r => r.Title.Contains(searchTerm).Boost(2f))
.Or(r => r.FileName.Contains(searchTerm).Boost(1.5f))
.Or(r => r.Content.Contains(searchTerm))
.Or(r => r.DocumentContents.Contains(searchTerm));
var individualWordsPredicate = PredicateBuilder.False<T>();
foreach (var term in searchTerm.Split(' '))
{
individualWordsPredicate
= individualWordsPredicate.And(r =>
r.Title.Contains(term).Boost(2f)
|| r.FileName.Contains(term).Boost(1.5f)
|| r.Content.Contains(term)
|| r.DocumentContents.Contains(term));
}
return PredicateBuilder.Or(actualPhrasePredicate.Boost(2f),
individualWordsPredicate);
}
实际的短语部分似乎运作良好。首先返回标题中包含完整短语的匹配。但是,如果我从短语的中间删除一个单词,则不会返回任何结果。
即。我有一个标题为“英格兰足球队很可怕”的页面,但是当我搜索“足球队是可怕的”时,它找不到该页面。
注意:页面可以附加文档,因此我想提升文件名,但不像页面标题那样高。
答案 0 :(得分:4)
我设法使用以下内容:
public static Expression<Func<T, bool>> GetSearchTermPredicate<T>(string searchTerm)
where T : ISearchableItem
{
var actualPhraseInTitlePredicate = PredicateBuilder.True<T>()
.And(r => r.Title.Contains(searchTerm));
var actualPhraseInFileNamePredicate = PredicateBuilder.True<T>()
.And(r => r.FileName.Contains(searchTerm));
var actualPhraseInContentPredicate = PredicateBuilder.True<T>()
.And(r => r.Content.Contains(searchTerm));
var actualPhraseInDocumentPredicate = PredicateBuilder.True<T>()
.And(r => r.DocumentContents.Contains(searchTerm));
var terms = searchTerm.Split(' ');
var titleContainsAllTermsPredicate = PredicateBuilder.True<T>();
foreach (var term in terms)
titleContainsAllTermsPredicate
= titleContainsAllTermsPredicate.And(r => r.Title.Contains(term).Boost(2f));
var fileNameAllTermsContains = PredicateBuilder.True<T>();
foreach (var term in terms)
fileNameAllTermsContains
= fileNameAllTermsContains.And(r => r.FileName.Contains(term));
var contentContainsAllTermsPredicate = PredicateBuilder.True<T>();
foreach (var term in terms)
contentContainsAllTermsPredicate
= contentContainsAllTermsPredicate.And(r => r.Content.Contains(term));
var documentContainsAllTermsPredicate = PredicateBuilder.True<T>();
foreach (var term in terms)
documentContainsAllTermsPredicate
= documentContainsAllTermsPredicate.And(r => r.DocumentContents.Contains(term));
var predicate = actualPhraseInTitlePredicate.Boost(3f)
.Or(actualPhraseInFileNamePredicate.Boost(2.5f))
.Or(actualPhraseInContentPredicate.Boost(2f))
.Or(actualPhraseInDocumentPredicate.Boost(1.5f))
.Or(titleContainsAllTermsPredicate.Boost(1.2f))
.Or(fileNameAllTermsContains.Boost(1.2f))
.Or(contentContainsAllTermsPredicate)
.Or(documentContainsAllTermsPredicate);
return predicate;
}
显然代码相当多,但我认为分离谓词更有助于提升工作效率。
以前代码的主要问题有两个:
PredicateBuilder.Or(actualPhrasePredicate.Boost(2f), individualWordsPredicate)
似乎不包含谓词“Or”。对结果联接谓词执行.ToString()
时,表达式不包含individualWordsPredicate
PredicateBuilder.False<T>()
作为individualWordsPredicate
。在查看表达式时,它基本上产生(False AND Field.Contains(keyword))
,当然永远不会评估为真。使用.True<T>()
修复此问题。