为什么CONTAINS在JCR-SQL2中找到不等的文本字符串?

时间:2018-01-03 12:37:22

标签: jcr jcr-sql2

使用JCR-SQL2查询我注意到CONTAINS运算符找到了节点 它与条件中没有完全相同的字符串。

实施例

以下查询:

SELECT * FROM [nt:base] AS s WHERE CONTAINS(s.*, 'my/search-expression')

不会只找到包含my/search-expression字符串的节点,也找不到包含my/another/search/expression字符串的节点。

为什么查询不能只找到提供的确切字符串?如何改变以缩小结果?

此问题旨在由我自己回答,用于知识共享 - 但您可以随意添加自己的答案或改进现有答案。

2 个答案:

答案 0 :(得分:3)

示例查询的执行计划揭示了问题的根本原因:

  [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"') */

查询现在将查找整个短语,而不是单个单词。但是,它仍然会忽略非单词字符,因此也可以找到这样的短语:"我的搜索表达式"或者" my-search-expression"。

2。使用LIKE表达式(不推荐)

如果您只想查找确切的短语,保留非单词字符,可以使用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-expression"。

3。使用双引号并细化结果

最好使用第一种方法(CONTAINS使用双引号)并稍后优化结果,例如在应用程序代码中如果从应用程序运行查询。

4。混合CONTAINS和LIKE

另一种选择是将全文搜索和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%') */

现在,它应该在同一时间快速而严格。

答案 1 :(得分:1)

有同样的问题。

因此,基本上,您应该为Lucene索引定义其他标记器,在我的情况下,“空白”标记器就可以了。

使用标准令牌生成器“ my / search-expression”分为3个令牌“ my”,“ search”和“ expression”。 标准令牌生成器使用一些特殊字符作为分隔符。

这就是为什么“ my / search-expression”获得0条结果的原因。

另一个例子:

带有空格标记生成器的“其他人我的搜索/表达式”分为:

“其他”,“我的”,“搜索/表达”

当您搜索“我的其他人”时,这应该返回结果。

List of tokenizers

Lucene索引示例:

api.add_resource(Events, '/events')
api.add_resource(tags, '/events/tag')
api.add_resource(location, '/events/location')