Sitecore搜索Predicate Builder多个关键字搜索,提升功能无法正常工作

Dav*_*ers 7 lucene lucene.net sitecore predicatebuilder sitecore8

我有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);
    }
Run Code Online (Sandbox Code Playgroud)

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

即我有一个标题为"英格兰足球队可怕"的页面,但当我搜索"足球队很可怕"时,它找不到该页面.

注意:页面可以附加文档,因此我想提高文件名,但不要像页面标题那样高.

Dav*_*ers 5

我设法使它与以下对象一起使用:

    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;
    }
Run Code Online (Sandbox Code Playgroud)

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

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

  1. PredicateBuilder.Or(actualPhrasePredicate.Boost(2f), individualWordsPredicate)似乎不包含谓词Or'd。在.ToString()结果联接谓词上执行时,该表达式不包含用于individualWordsPredicate
  2. 在固定后,它仍然没有工作,这是因为我用PredicateBuilder.False<T>()individualWordsPredicate。当看表达式时,它基本上是在产生(False AND Field.Contains(keyword))哪个,当然永远不会评估为真。使用.True<T>()固定的。