在使用JCR-SQL2查询时,我注意到CONTAINS操作符查找的节点不具有与条件完全相同的字符串。
示例
以下查询:
SELECT * FROM [nt:base] AS s WHERE CONTAINS(s.*, 'my/search-expression')不会只找到包含my/search-expression字符串的节点,也不会找到具有字符串(如my/another/search/expression )的节点。
为什么查询没有找到所提供的确切字符串?如何才能改变它以缩小结果?
为了分享知识,这个问题是由我来回答的--但是可以自由地添加你自己的答案,或者改进一个现有的答案。
发布于 2018-01-03 12:37:21
示例查询的执行计划揭示了问题的根源:
[nt:base] as [s] /* lucene:lucene(/oak:index/lucene) +:fulltext:my +:fulltext:search +:fulltext:expression ft:("my/search-expression") where contains([s].[*], 'my/search-expression') */CONTAINS运算符触发全文搜索。非单词字符,如"/“或"-",用作单词分隔符。因此,查询将查找所有包含单词"my“、"search”和“表达式”的节点。
它能做些什么?有几种选择。
1.使用双引号
如果您希望将结果限制在具有给定单词的短语中,并且在它们之间没有任何其他单词,请将搜索表达式放在双引号中:
SELECT * FROM [nt:base] AS s WHERE CONTAINS(s.*, '"my/search-expression"')现在,执行计划是不同的:
[nt:base] as [s] /* lucene:lucene(/oak:index/lucene) :fulltext:"my search expression" ft:("my/search-expression") where contains([s].[*], '"my/search-expression"') */现在,查询将查找整个短语,而不是单个单词。然而,它仍然忽略非单词字符,因此也会找到这样的短语:“我的搜索表达式”或“我的搜索表达式”。
2.使用类似的表达式(不建议使用)
如果只想找到保留非单词字符的确切短语,可以使用LIKE表达式:
SELECT * FROM [nt:base] AS s WHERE s.* LIKE '%my/search-expression%'然而,这是慢得多的。在解释执行计划时,我需要添加另一个条件以避免超时。对于此查询:
SELECT * FROM [nt:base] AS s WHERE s.* LIKE '%my/search-expression%' AND ISDESCENDANTNODE([/content/my/content]) 执行计划是:
[nt:base] as [s] /* traverse "/content/my/content//*" where ([s].[*] like '%my/search-expression%') and (isdescendantnode([s], [/content/my/content])) */它只会找到带有以下短语的节点:“my/search-表达式”。
3.使用双引号并改进结果
最好是使用第一种方法(带有双引号的CONTAINS),并在以后细化结果,例如,在应用程序代码中,如果查询是从应用程序运行的。
4.混合含有和类似物
另一种选择是将全文搜索和LIKE表达式与AND混合使用。
SELECT * FROM [nt:base] AS s WHERE CONTAINS(s.*, '"my/search-expression"') AND s.* LIKE '%my/search-expression%'现在的执行计划是:
[nt:base] as [s] /* lucene:lucene(/oak:index/lucene) :fulltext:"my search expression" ft:("my/search-expression") where (contains([s].[*], '"my/search-expression"')) and ([s].[*] like '%my/search-expression%') */现在,它应该是快速和严格的同时。
发布于 2020-09-08 10:54:07
也有同样的问题。
因此,基本上您应该为lucene索引定义不同的标记器,在我的例子中,“空格”标记器很好。
使用标准标记器,“my/search-表达式”被拆分为3个标记"my“、"search”、“表达式”。标准标志符使用一些特殊字符作为分隔符。
这就是为什么“我/搜索-表达式”得到0的原因。
另一个例子是:
“一些-其他我的搜索/表达式”,与空格标记器,这是分裂成:
“一些-其他”、“我的”、“搜索/表达”
当您搜索“一些-其他我的”,这应该会返回结果。
Lucene索引示例:
<yourLucene
jcr:primaryType="oak:QueryIndexDefinition"
type="lucene"
async="async"
evaluatePathRestrictions="{Boolean}true"
includedPaths="[/somepath]"
queryPaths="[/somepath]"
compatVersion="{Long}2">
<analyzers jcr:primaryType="nt:unstructured">
<default jcr:primaryType="nt:unstructured">
<tokenizer
jcr:primaryType="nt:unstructured"
name="Whitespace"/>
<filters jcr:primaryType="nt:unstructured">
<Standard jcr:primaryType="nt:unstructured"/>
<LowerCase jcr:primaryType="nt:unstructured"/>
<Stop jcr:primaryType="nt:unstructured"/>
</filters>
</default>
</analyzers>
<indexRules jcr:primaryType="nt:unstructured">
<nt:unstructured jcr:primaryType="nt:unstructured">
<properties jcr:primaryType="nt:unstructured">
<someprop
jcr:primaryType="nt:unstructured"
name="someprop"
propertyIndex="{Boolean}true"
type="String"/>
</properties>
</nt:unstructured>
</indexRules>https://stackoverflow.com/questions/48077571
复制相似问题