JCR-SQL - 包含函数不会转义特殊字符吗?

时间:2018-04-06 13:45:06

标签: lucene aem cq5 jcr jcr-sql2

我有以下查询字符串:

SELECT jcr:title, jcr:created, jcr:description FROM cq:PageContent WHERE jcr:path LIKE '/content/.../%' AND CONTAINS (., '*') ORDER BY date ASC

问题是查询返回给定路径中的所有节点,即使它们在任何原型中都没有星号。我想逃避星号字符,但结果是一样的。我尝试过这样的事情:

SELECT jcr:title, jcr:created, jcr:description FROM cq:PageContent WHERE jcr:path LIKE '/content/.../%' AND CONTAINS (., '\*') ORDER BY date ASC

甚至是这样的:

SELECT jcr:title, jcr:created, jcr:description FROM cq:PageContent WHERE jcr:path LIKE '/content/.../%' AND CONTAINS (., '\*\*\*\*\*\*\*\*\*\*\*') ORDER BY date ASC

在所有这些查询中,结果是相同的,即使这些页面都没有包含星号字符(或其中11个)的属性

documentation of jcr:contains function说:

  

在单引号(“'”)的searchexp文字实例中,双引号(“"”)和连字符(“ - ”)必须使用反斜杠(“\”)进行转义。因此,反斜杠本身也必须进行转义,最终为双反斜杠(“\”)。

其他字符如*未被提及,因此即使没有任何转义(?)也应该有效。请让我理解为什么我在这里得到这样的结果以及如何正确地逃避这些结果。

3 个答案:

答案 0 :(得分:2)

您输入的文档有答案。你必须要转义特殊字符,但是如果你想要一些像星号这样的字面只能匹配字符'*',那么你必须使用转义字符作为反斜杠。文档声明有点令人困惑的是,在解析字符串时反斜杠本身是一个特殊字符,因此如果您希望将反斜杠视为转义字符,则需要将其转义。

换句话说,要转义星号,您需要将其写为

\\*

答案 1 :(得分:1)

我不确定,jcr:contains是否适合您。也许jcr:like是你想要的更好的方法。

jcr:contains是全文搜索,并使用lucene索引。因此可能会产生一些意想不到的影响它也不能轻易地与其他索引结合使用。

jcr:like是与通配符的属性比较。这个通配符可以用反斜杠转义。 (https://docs.adobe.com/docs/en/spec/jcr/1.0/6.6.5.1_jcr_like_Function.html

第一个示例SQL-2查询

在任何属性中使用*搜索cq:PageContent节点。 %(百分号)是通配符。搜索*。

SELECT * FROM [cq:PageContent] AS content
WHERE ISDESCENDANTNODE('/content/myproject/...')
AND content.* LIKE '%*%'

第二个示例SQL-2查询

在任何属性中使用%搜索cq:PageContent节点。因此百分号用\%进行转义(并由通配符%包围)。

SELECT * FROM [cq:PageContent] AS content
WHERE ISDESCENDANTNODE('/content/myproject/...')
AND content.* LIKE '%\%%'

第3个XPath查询示例

与上一个几乎相同,就像XPath查询一样。只有我不知道如何搜索任何属性。所以这个例子搜索jcr:title属性。

/jcr:root/content/myproject/...//element(*, cq:PageContent)[jcr:like(@jcr:title, '%\%%')]

答案 2 :(得分:0)

我终于在Jackrabbit Wiki page

找到了答案
  

在全文(包含)子句中转义文本

     

Jackrabbit Oak使用Apache Lucene grammar for fulltext search。因此,要转义用户提供的文本以便在contains中使用,您需要过滤掉所有特殊字符,或者将其转义。例如,要过滤掉特殊字符,请使用:

     

String filteredContains = searchTerm.replaceAll("[\\Q+-&|!(){}[]^\"~*?:\\/\\E]", ""); String q = "/jcr:root/foo/element(*, foo)" + "[jcr:contains(@title, '" + filteredContains.replaceAll("'", "''") + "')]" + "[@itemID = '" + itemID.replaceAll("'", "''") + "']";

     

仅适用于Jackrabbit 2.x:使用Text.escapeIllegalXpathSearchChars(...)来调用jcr:contains(...)(另请参阅JCR-1248):

     

String q = "/jcr:root/foo/element(*, foo)" + "[jcr:contains(@title, '" + Text.escapeIllegalXpathSearchChars(searchTerm).replaceAll("'", "''") + "')]" + "[@itemID = '" + itemID.replaceAll("'", "''") + "']";