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

时间:2016-07-08 08:10:50

标签: lucene sitecore lucene.net sitecore8 predicatebuilder

我的sitecore pages / lucene文档包含以下字段:

  • 标题
  • 文件名
  • 内容
  • 文件内容

我正在创建这些搜索并具有以下要求:

  • 应首先返回 title 字段中包含整个短语的匹配。
  • 应该在 filename 字段中输入包含整个短语的匹配。
  • 内容中包含整个短语的点击数应返回第三个
  • 文件内容中包含整个短语的匹配应返回第四个
  • 标题字段中包含所有关键字(按任意顺序)的匹配应返回第五位
  • 文件名字段中包含所有关键字(按任意顺序)的匹配应返回第六位
  • 内容中包含所有关键字(按任意顺序)的匹配应返回第七位。
  • 文件内容中包含所有关键字(按任意顺序)的匹配应返回第八位。

这就是我所拥有的:

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

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

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

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

1 个答案:

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

显然代码相当多,但我认为分离谓词更有助于提升工作效率。

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

  1. PredicateBuilder.Or(actualPhrasePredicate.Boost(2f), individualWordsPredicate)似乎不包含谓词“Or”。对结果联接谓词执行.ToString()时,表达式不包含individualWordsPredicate
  2. 的任何内容
  3. 在确定它仍然无法正常工作之后,这是因为我使用PredicateBuilder.False<T>()作为individualWordsPredicate。在查看表达式时,它基本上产生(False AND Field.Contains(keyword)),当然永远不会评估为真。使用.True<T>()修复此问题。
相关问题