如何使用 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 中嵌套查询的优先级? 的相关文章

  • 未提供参数时如何指定 C# System.Commandline 行为?

    在我的控制台应用程序中 当未提供控制台参数时 将执行我指定列表 在本例中为参数 3 的任何处理程序 调用该处理程序时 布尔参数设置为 false 但对我来说 根本不调用它更有意义 如何防止这种情况发生并显示帮助文本 using System
  • 为什么 int8_t 和用户通过 cin 输入显示奇怪的结果[重复]

    这个问题在这里已经有答案了 一小段代码让我发疯 但希望你能阻止我跳出窗外 看这里 include
  • 如何将非静态类成员“std::bind”绑定到 Win32 回调函数“WNDPROC”?

    我正在尝试将非静态类成员绑定到标准WNDPROC http msdn microsoft com en us library ms633573 aspx功能 我知道我可以通过将类成员设为静态来简单地做到这一点 但是 作为一名 C 11 ST
  • 在 LINQ 中按 Id 连接多表和分组

    我想按categoryId显示列表产品的名称组 这是我的代码 我想要我的视图显示结果 Desktop PC HP Red PC Dell Yellow PC Asus Red SmartPhone Lumia 720 Blue 我的组模型
  • 在 C 中匹配二进制模式

    我目前正在开发一个 C 程序 需要解析一些定制的数据结构 幸运的是我知道它们是如何构造的 但是我不确定如何在 C 中实现我的解析器 每个结构的长度都是 32 位 并且每个结构都可以通过其二进制签名来识别 举个例子 有两个我感兴趣的特定结构
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • 如何创建包含 IPv4 地址的文本框? [复制]

    这个问题在这里已经有答案了 如何制作一个这样的文本框 我想所有的用户都见过这个并且知道它的功能 您可以使用带有 Mask 的 MaskedTestBox000 000 000 000 欲了解更多信息 请参阅文档 http msdn micr
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 我可以使用 moq Mock 来模拟类而不是接口吗?

    正在经历https github com Moq moq4 wiki Quickstart https github com Moq moq4 wiki Quickstart 我看到它 Mock 一个接口 我的遗留代码中有一个没有接口的类
  • DbContext 和 ObjectContext 有什么区别

    From MSDN 表示工作单元和存储库模式的组合 使您能够查询数据库并将更改分组在一起 然后将这些更改作为一个单元写回存储 DbContext在概念上类似于ObjectContext 我虽然DbContext只处理与数据库的连接以及针对数
  • 如何在 32 位或 64 位配置中以编程方式运行任何 CPU .NET 可执行文件?

    我有一个可在 32 位和 64 位处理器上运行的 C 应用程序 我试图枚举给定系统上所有进程的模块 当尝试从 64 位应用程序枚举 32 位进程模块时 这会出现问题 Windows 或 NET 禁止它 我认为如果我可以从应用程序内部重新启动
  • 如何禁用 fread() 中的缓冲?

    我正在使用 fread 和 fwrite 读取和写入套接字 我相信这些函数用于缓冲输入和输出 有什么方法可以在仍然使用这些功能的同时禁用缓冲吗 Edit 我正在构建一个远程桌面应用程序 远程客户端似乎 落后于服务器 我不知道可能是什么原因
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 如何设置 log4net 每天将我的文件记录到不同的文件夹中?

    我想将每天的所有日志保存在名为 YYYYMMdd 的文件夹中 log4net 应该根据系统日期时间处理创建新文件夹 我如何设置它 我想将一天中的所有日志保存到 n 个 1MB 的文件中 我不想重写旧文件 但想真正拥有一天中的所有日志 我该如
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成
  • 使用 C# 读取 Soap 消息

  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 调用堆栈中的“外部代码”是什么意思?

    我在 Visual Studio 中调用一个方法 并尝试通过检查调用堆栈来调试它 其中一些行标记为 外部代码 这到底是什么意思 方法来自 dll已被处决 外部代码 意味着该dll没有可用的调试信息 你能做的就是在Call Stack窗口中单
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装
  • Oracle Data Provider for .NET 不支持 Oracle 19.0.48.0.0

    我们刚刚升级到 Oracle 19c 19 3 0 所有应用程序都停止工作并出现以下错误消息 Oracle Data Provider for NET 不支持 Oracle 19 0 48 0 0 我将 Oracle ManagedData

随机推荐