Sitecore Search Predicate Builder 多关键字搜索,提升功能无法按预期工作

Sitecore Search Predicate Builder multiple keyword search with boosting not working as desired

我有包含以下字段的 sitecore 页面/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);
    }

实际的短语部分似乎效果不错。首先返回标题中包含完整短语的匹配项。但是,如果我从短语中间删除一个词,则不会返回任何结果。

即我有一个标题为 "The England football team are dreadful" 的页面,但是当我使用 "The football team are dreadful" 进行搜索时,它找不到该页面。

注意:页面可以附加文档,所以我也想提升文件名,但不要像页面标题那样高。

我设法让它与以下内容一起工作:

    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;
    }

显然代码要多一些,但我认为分离谓词对于提升有效工作更有意义。

之前代码的主要问题有两个:

  1. PredicateBuilder.Or(actualPhrasePredicate.Boost(2f), individualWordsPredicate) 似乎不包括被 Or'd 的谓词。在对生成的连接谓词执行 .ToString() 时,表达式不包含 individualWordsPredicate
  2. 的任何内容
  3. 修复后还是不行,这是因为我用的是PredicateBuilder.False<T>()作为individualWordsPredicate。当查看表达式时,它基本上产生 (False AND Field.Contains(keyword)) 当然永远不会计算为真。使用 .True<T>() 解决了这个问题。