gpt4 book ai didi

c# - 如何使用Solr Provider在Sitecore ContentSearch中控制嵌套查询的优先级?

转载 作者:行者123 更新时间:2023-11-30 12:25:26 30 4
gpt4 key购买 nike

版本详细信息:我正在使用Solr v4.7作为搜索引擎/索引服务器的Sitecore 7.5内部版本141003。我还使用没有自定义索引器的标准Sitecore Solr提供程序。

目标目标:
我使用带有PredicateBuilder的Sitecore ContentSearch LINQ来编译一些灵活的嵌套查询。当前,我需要在特定的“根项目”中搜索,同时排除名称中带有“文件夹”的模板,还排除其路径中带有“ / testing”的项目。在某些时候,“根项目”可以是多个项目,路径也可以包含(当前仅是“ / testing”。在这种情况下,我们的想法是使用PredicateBuilder来构建外部“ AND”谓词,并使用内部“多个“根项目”和路径排除的“或”。

问题:
目前,我正在处理有关这些谓词/条件的嵌套顺序和优先级的问题。我已经在测试几种方法和组合,但是我一直遇到的问题是!TemplateName.Contains和Item [“ _ fullpath”]。Contains优先于Paths.Contains,最终每次导致0结果。

我正在使用Search.log来检查查询输出,并且我已经针对Solr管理员进行了手动测试,并针对它运行查询以比较结果。在下面,您将找到我尝试使用Sitecore Linq进行组合的示例,以及它们为Solr生成的查询。

原始代码示例:

带有根项目列表的原始测试

// sometimes will be 1, sometimes will be multiple
var rootItems = new List<ID> { pathID }; // simplified to 1 item for now
var query = context.GetQueryable<SearchResultItem>();
var folderFilter = PredicateBuilder.True<SearchResultItem>().And(i => !i.TemplateName.Contains("folder") && !i["_fullpath"].Contains("/testing"));
var pathFilter = PredicateBuilder.False<SearchResultItem>();
pathFilter = rootItems.Aggregate(pathFilter, (current, id) => current.Or(i => i.Paths.Contains(id)));
folderFilter = folderFilter.And(pathFilter);
query.Filter(folderFilter).GetResults();


查询输出:(-_templatename:(*文件夹*)AND -_fullpath:(* / testing *))AND _path:(730c169987a44ca7a9ce294ad7151f13)

如您在上面的输出中看到的,两个“不包含”过滤器周围有一个内部括号,它优先于路径一。当我在Solr管理员中运行此确切查询时,它将返回0个结果。但是,如果我删除了内部括号,因此它全部是一个“ AND”集,它将返回预期的结果。

我使用PredicateBuilder的不同组合和方法进一步进行了测试,每种组合都导致相同的查询。我什至尝试将两个单独的过滤器(“ query.Filter(pred1).Filter(pred2)”)添加到我的主查询对象中,并且结果相同。

其他代码示例:

Alt。 1-直接在文件夹过滤器中添加“ Paths.Contains”

var query = context.GetQueryable<SearchResultItem>();
var folderFilter = PredicateBuilder.True<SearchResultItem>().And(i => !i.TemplateName.Contains("folder") && !i["_fullpath"].Contains("/testing"));
folderFilter = folderFilter.And(i => i.Paths.Contains(pathID));
query.Filter(folderFilter).GetResults();


查询输出:(-_templatename:(*文件夹*)AND -_fullpath:(* / testing *))AND _path:(730c169987a44ca7a9ce294ad7151f13)

Alt 2-两个谓词加入第一个

var query = context.GetQueryable<SearchResultItem>();
var folderFilter = PredicateBuilder.True<SearchResultItem>().And(i => !i.TemplateName.Contains("folder") && !i["_fullpath"].Contains("/testing"));
var pathFilter = PredicateBuilder.False<SearchResultItem>().Or(i => i.Paths.Contains(pathID));
folderFilter = folderFilter.And(pathFilter);
query.Filter(folderFilter).GetResults();


查询输出:(-_templatename:(*文件夹*)AND -_fullpath:(* / testing *))AND _path:(730c169987a44ca7a9ce294ad7151f13)

Alt 3-两个“内部”谓词,一个用于“ Not”,一个用于“ Paths”,这些谓词连接到外部谓词

var query = context.GetQueryable<SearchResultItem>();
var folderFilter = PredicateBuilder.True<SearchResultItem>().And(i => !i.TemplateName.Contains("folder") && !i["_fullpath"].Contains("/testing"));
var pathFilter = PredicateBuilder.False<SearchResultItem>().Or(i => i.Paths.Contains(pathID));
var finalPredicate = PredicateBuilder.True<SearchResultItem>().And(folderFilter).And(pathFilter);
query.Filter(finalPredicate).GetResults();


查询输出:(-_templatename:(*文件夹*)AND -_fullpath:(* / testing *))AND _path:(730c169987a44ca7a9ce294ad7151f13)

结论:
最终,我正在寻找一种方法来控制这些嵌套查询/条件的优先级,或者如何构建它们以首先放置路径,然后放置“非”过滤器。如前所述,在某些情况下,我们将需要查询更多类似以下内容的“根项目”和多个路径排除项:


  (-_templatename:(*文件夹*)AND -_fullpath:(* /测试*)AND
  (_path:(730c169987a44ca7a9ce294ad7151f13)OR
  _path:(12c1aa7f60fa4e8d9f0a983bbbb40d8b)))


要么


  (-_templatename:(*文件夹*)AND -_fullpath:(* /测试*)AND
  (_path:(730c169987a44ca7a9ce294ad7151f13)))


当我直接在Solr管理员中运行它们时,这两个查询都返回我期望/需要的结果。但是,我似乎无法提出使用Sitecore ContentSearch Linq以这种方式输出查询的方法或操作顺序。

其他人是否有我如何实现此目标的经验?根据建议,如果可以将其嫁接到IQueryable上以调用“ GetFacets”和“ GetResults”,我也愿意在不使用Sitecore Linq的情况下组装此查询。

更新:
我没有包括我所做的所有修订,因为这样可能会使我丧命多久。就是说,我确实在原始示例(顶部)上进行了其他一些细微改动,结果与其他示例相似:

var folderFilter = PredicateBuilder.True<SearchResultItem>().And(i => !i.TemplateName.Contains("folder")).And(i => !i["_fullpath"].Contains("/testing"));
var rootItems = new List<ID> { pathID, path2 };
// or paths separately
var pathFilter = PredicateBuilder.False<SearchResultItem>();
pathFilter = rootItems.Aggregate(pathFilter, (current, id) => current.Or(i => i.Paths.Contains(id)));
var finalPredicate = folderFilter.And(pathFilter);
var query = context.GetQueryable<SearchResultItem>();
query.Filter(finalPredicate).GetResults();


查询输出:((-_templatename:(*文件夹*)AND -_fullpath:(* / testing *))AND(_path:(730c169987a44ca7a9ce294ad7151f13)或_path:((12c1aa7f60fa4e8d9f0a983bbbb40d8b)))

仍然是围绕“ _templatename”和“ _fullpath”条件的那些内括号引起问题。

谢谢。

最佳答案

好的,我在这里提出了这个问题,并将情况也发布到了Sitecore支持下,我刚刚收到了回复和一些其他信息。

根据Solr Wiki(http://wiki.apache.org/solr/FAQ),在“搜索”部分中,为什么“ foo AND -baz”与文档匹配,但“ foo AND(-bar)”与文档不匹配?回答为什么结果返回0。


  布尔查询必须至少具有一个“正”表达式(即,必须或应该)才能匹配。 Solr试图解决这个问题,如果要求执行一个布尔查询,该布尔查询仅在最顶层包含否定子句,则会添加一个匹配所有文档的查询(即::)
  
  如果顶层BoolenQuery在其中的某个位置包含嵌套的BooleanQuery,该嵌套的BooleanQuery仅包含否定子句,则该嵌套查询将不会被修改,并且(根据定义)它不匹配任何文档-如果需要,则意味着外部查询将不匹配。


我不确定在Sitecore Solr提供程序中构造查询的方式是完全完成的,还是不确定为什么它们将嵌套查询中的负数归为一组,但是仅包含负数的嵌套查询会按预期返回0结果doc。然后,诀窍是向子查询添加“全部匹配”查询(*:*)。

支持代表无需手动对我认为可能会遇到这种情况的任何查询执行此操作,而是提供了修补程序DLL来替换提供程序,该提供程序将自动修改嵌套查询以解决此问题。

他们还将此记录为错误,并提供了此问题的参考号398622。

现在,结果查询如下所示:

((-_templatename:(*folder*) AND -_fullpath:(*/testing*) AND *:*) AND _path:(730c169987a44ca7a9ce294ad7151f13))


或者,对于多个查询:

((-_templatename:(*folder*) AND -_fullpath:(*/testing*) AND *:*) AND (_path:(730c169987a44ca7a9ce294ad7151f13) OR _path:(12c1aa7f60fa4e8d9f0a983bbbb40d8b)))


并且结果按预期返回。如果遇到其他问题,我将在Sitecore支持下使用参考号,看看他们是否可以提供补丁。您还必须更新Solr.Index和Solr.Indexes.Analytics配置文件中使用的提供程序。

关于c# - 如何使用Solr Provider在Sitecore ContentSearch中控制嵌套查询的优先级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31458086/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com