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, '%\%%')]
我有以下查询字符串:
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, '%\%%')]