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

JCR-SQL - contains function doesn't escape special characters?

我有以下查询字符串:

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

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

documentation of jcr:contains function 说:

Within the searchexp literal instances of single quote (“'”), double quote (“"”) and hyphen (“-”) must be escaped with a backslash (“\”). Backslash itself must therefore also be escaped, ending up as double backslash (“\”).

其他字符如 * 未提及,因此即使没有任何转义 (?),它也应该可以工作。请让我明白为什么我会在这里得到这样的结果,以及如何正确地转义这些字符。

您输入的文档中有答案。有些特殊字符你必须转义,但是如果你想要一些文字如星号只匹配字符“*”那么你必须使用反斜杠转义字符。文档说明有点令人困惑的是,反斜杠本身在解析字符串时是一个特殊字符,因此如果您希望反斜杠被视为转义字符,则需要对其进行转义。

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

\*

我终于在 Jackrabbit Wiki page

上找到了答案

Escaping text in fulltext (contains) clauses

Jackrabbit Oak uses the Apache Lucene grammar for fulltext search. So to escape user-supplied text for use in contains, you will need to either filter out all the special characters, or escape them. So for example, to filter out the special characters, use:

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

Only for Jackrabbit 2.x: use Text.escapeIllegalXpathSearchChars(...) for calls to jcr:contains(...) (see also JCR-1248):

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

我不确定 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 '%\%%'

第三个 XPath 查询示例

和上一个差不多,就是XPath查询。只有我不知道,您如何搜索任何属性。所以这个例子搜索 jcr:title 属性。

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