首先,我要说的是,我对JSR-170和Jackrabbit / Lucene一般都很陌生。
我有以下XPath查询:
//*[@sling:resourceType="users/user-profile" and jcr:contains(*/*/*,'sophie\-a')] order by @jcr:score descending
我有一个名叫Sophie-Allen的用户和一个名叫Sophie-Anne的用户。使用上面的查询进行搜索会返回零结果,其中单独搜索'sophie'会返回两个用户。我知道连字符意味着在JSR-170中排除,但我已经将其转义(如上所示)。
为什么此查询不返回两个用户?
另一个奇怪的事情是当我使用星号时(连字符在执行时都被转义):
'sophie-allen'
会返回Sophie-Allen的记录。 'soph*'
将返回Sophie-Allen和Sophie-Anne。 'sophie-a*
不会返回任何内容。 'sophie-allen*'
不会返回任何内容。据我所知,使用jcr:contains,从技术上讲你不需要使用星号,但看看上面的行为,它似乎有某种影响。
在XPath查询和搜索JCR时,是否还有其他关于连字符和星号的内容?我用谷歌搜索了我能想到的所有内容并通过规范阅读,但似乎无法找到任何可以回答我问题的内容。
提前致谢。
修改 它看起来像'短语查询'不适用于jcr:contains(不再?)作为默认的Lucene Analyzer在连字符上标记,意味着它将'sophie-allen'分割为sophie和allen。
编辑2: 我已经尝试过使用Jackrabbit用户列表中某人建议的自定义分析器和标记器,但这也没有帮助,Lucene仍然使用连字符并省略了我想要的结果。
答案 0 :(得分:2)
你是对的,Lucene确实将“sophie-allen”分成两个代币,但这些代币是相邻的。你说过你尝试过这样的短语表达式:
... jcr:contains(*/*/*,'"sophie-a*"') ...
这应该通过找到令牌“sophie”,然后是另一个包含'a'作为第一个字符的令牌来工作。因为在索引期间使用的相同分析器应该用于标记此短语表达式,所以' - '字符仍将用作分隔符[1]。 (请注意,如果您在Java代码中指定XPath表达式,则必须使用前面的反斜杠转义双引号字符。)
但是,如果这不起作用,您可以尝试在此表达式中取出连字符。因为您正在使用通配符,所以逻辑可能会错误地将通配符表达式标记化。换句话说,尝试:
... jcr:contains(*/*/*,'"sophie a*"') ...
当然,如果没有通配符,这可能会起作用(有或没有连字符):
... jcr:contains(*/*/*,'"sophie-allen"') ...
祝你好运!
P.S。我没有证实这适用于Jackrabbit,但它在ModeShape(也使用Lucene)中有效。
[1]确切的规则取决于标记器。例如,StandardTokenizer会过滤掉英文停用词,但会对“ - ”字符进行标记,除非令牌中有数字(在这种情况下,整个令牌被解释为产品且不会被拆分。
答案 1 :(得分:1)
在与同事合作时,我们发现了ModeShape的这个JIRA,偶然记录了Randall(他也在这里回答)。事实证明,这个问题是由于长臂猿没有正确/太好地使用通配符在搜索词中处理通配符这一事实。
兰德尔已经为ModeShape做了一个修复,但我的同事和项目团队提名不要在现阶段解决我们的问题,因为使用Jackrabbit不是100%肯定。我想将这个问题的答案与兰德尔联系起来,但他的帖子并不是真正的答案。我会把这篇文章标记为答案,除非兰德尔出现并张贴一些东西。