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

2024-04-11

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

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

Problem:目前,我正在处理有关这些谓词/条件的嵌套顺序和优先级的问题。我一直在测试几种方法和组合,但我不断遇到的问题是 !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:(*folder*) 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:(*folder*) 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:(*folder*) 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:(*folder*) AND -_fullpath:(*/testing*)) AND _path:(730c169987a44ca7a9ce294ad7151f13)

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

(-_templatename:(*folder*) AND -_fullpath:(*/testing*) AND (_路径:(730c169987a44ca7a9ce294ad7151f13)或 _路径:(12c1aa7f60fa4e8d9f0a983bbbb40d8b)))

OR

(-_templatename:(*folder*) AND -_fullpath:(*/testing*) AND (_路径:(730c169987a44ca7a9ce294ad7151f13)))

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

还有其他人有我如何实现这一目标的经验吗?根据建议,如果我可以将其与 IQueryable 结合起来以调用“GetFacets”和“GetResults”,我也愿意在不使用 Sitecore Linq 的情况下组装这部分查询。

Update:我没有包括我所做的所有修订,因为这样可能会杀了我多久。也就是说,我确实在原始示例(顶部)的基础上尝试了另一种细微的变化,其结果与其他示例类似:

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:(*folder*) AND -_fullpath:(*/testing*)) AND (_path:(730c169987a44ca7a9ce294ad7151f13) OR _path:(12c1aa7f60fa4e8d9f0a983bbbb40d8b)))

导致问题的仍然是“_templatename”和“_fullpath”条件周围的内括号。

Thanks.


好吧,我在这里提出了这个问题,并将情况发布给了 Sitecore 支持,我刚刚收到了回复和一些附加信息。

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

布尔查询必须至少有一个“正”表达式(即;必须或应该)才能匹配。 Solr 尝试帮助解决此问题,如果要求执行仅包含否定子句的 BooleanQuery在最顶层,它添加了一个匹配所有文档的查询(即::)

如果顶级 BoolenQuery 在其内部某处包含一个仅包含否定子句的嵌套 BooleanQuery,则该嵌套查询将不会被修改,并且它(根据定义)不匹配任何文档 - 如果需要,这意味着外部查询将不匹配。

我不确定在 Sitecore Solr 提供程序中构建查询完全做了什么,或者为什么他们将负数分组在嵌套查询中,但根据 Solr 的说法,仅包含负数的嵌套查询按预期返回 0 结果文档。那么,诀窍就是向子查询添加“匹配所有”查询 (*:*)。

而不必对我的任何查询手动执行此操作think可能会遇到这种情况,支持代表提供了一个补丁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 配置文件中使用的提供程序。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Solr Provider 控制 Sitecore ContentSearch 中嵌套查询的优先级? 的相关文章

  • Mono 无法保存用户设置

    我在 Mono Ubuntu 上保存用户设置时遇到问题 这是代码示例 private void Form1 Load object sender EventArgs e string savedText Properties Setting
  • MEX 文件中的断言导致 Matlab 崩溃

    我正在使用mxAssert 宏定义为matrix h在我的 C 代码中 mex 可以完美编译 当我调用的 mex 代码中违反断言时 该断言不会导致我的程序崩溃 而是导致 Matlab 本身崩溃 我错过了什么吗 这是有意的行为吗 当我查看 M
  • 添加对共享类的多个 WCF 服务的服务引用

    我正在尝试将我的 WCF Web 服务拆分为几个服务 而不是一个巨大的服务 但是 Visual Studio Silverlight 客户端 复制了两个服务共享的公共类 这是一个简单的例子来说明我的问题 在此示例中 有两个服务 两者都返回类
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • Guid 应包含 32 位数字和 4 个破折号

    我有一个包含 createuserwizard 控件的网站 创建帐户后 验证电子邮件及其验证 URL 将发送到用户的电子邮件地址 但是 当我进行测试运行时 单击电子邮件中的 URL 时 会出现以下错误 Guid should contain
  • 调试内存不足异常

    在修复我制作的小型 ASP NET C Web 应用程序的错误时 我遇到了 OutOfMemoryException 没有关于在哪里查看的提示 因为这是一个编译时错误 如何诊断此异常 我假设这正是内存分析发挥作用的地方 有小费吗 Thank
  • 如何在 VS 中键入时显示方法的完整文档?

    标题非常具有描述性 是否有任何扩展可以让我看到我正在输入的方法的完整文档 我想查看文档 因为我可以在对象浏览器中看到它 其中包含参数的描述和所有内容 而不仅仅是一些 摘要 当然可以选择查看所有覆盖 它可能是智能感知的一部分 或者我不知道它并
  • VS30063:您无权访问 https://dev.azure.com

    我正在尝试在 asp net core 2 1 mvc 应用程序中使用以下代码连接 Azure DevOps Uri orgUrl new Uri https dev azure com xxxxx String personalAcces
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • C++11 函数局部静态 const 对象的线程安全初始化

    这个问题已在 C 98 上下文中提出 并在该上下文中得到回答 但没有明确说明有关 C 11 的内容 const some type create const thingy lock my lock some mutex static con
  • 在 C# 中将位从 ulong 复制到 long

    所以看来 NET 性能计数器类型 http msdn microsoft com en us library system diagnostics performancecounter aspx有一个恼人的问题 它暴露了long对于计数器
  • 转到 C# WPF 中的第一页

    我正在 WPF 中使用导航服务 为了导航到页面 我使用 this NavigationService Navigate new MyPage 为了返回我使用 this NavigationService GoBack 但是如何在不使用的情况
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • std::bind 重载解析

    下面的代码工作正常 include
  • C# using 语句、SQL 和 SqlConnection

    使用 using 语句 C SQL 可以吗 private static void CreateCommand string queryString string connectionString using SqlConnection c
  • 如何排列表格中的项目 - MVC3 视图 (Index.cshtml)

    我想使用 ASP NET MVC3 显示特定类型食品样本中存在的不同类型维生素的含量 如何在我的视图 Index cshtml 中显示它 an example 这些是我的代码 table tr th th foreach var m in
  • 从匿名类型获取值

    我有一个方法如下 public void MyMethod object obj implement 我这样称呼它 MyMethod new myparam waoww 那么我该如何实施MyMethod 获取 myparam 值 Edit
  • 如何在 GCC 5 中处理双 ABI?

    我尝试了解如何克服 GCC 5 中引入的双重 ABI 的问题 但是 我没能做到 这是一个重现错误的非常简单的示例 我使用的GCC版本是5 2 如您所见 我的主要函数 在 main cpp 文件中 非常简单 main cpp include
  • Azure函数版本2.0-应用程序blobTrigger不工作

    我有一个工作功能应用程序 它有一个 blob 输入和一个事件中心输出 在测试版中工作 随着最新的更改 我的功能不再起作用 我尝试根据发行说明更新 host json 文件 但它没有引用 blob 触发器 version 2 0 extens

随机推荐