JCR-SQL - содержит функцию, не экранирующую специальные символы?

У меня есть следующая строка запроса:

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 из них)

Документация по функции jcr: содержит:

Внутри литеральных поисковых выражений экземпляры одинарной кавычки ("'"), двойная кавычка ("" ") и дефис (" - ") должны быть экранированы с помощью обратной косой черты (" \ "). Поэтому саму обратную косую черту также следует экранировать, заканчивая тем, что как двойной обратный слеш ("\").

Другие персонажи, такие как * не упоминаются, поэтому он должен работать даже без выхода (?). Пожалуйста, дайте мне понять, почему я получаю такие результаты здесь и как правильно избежать таких символов.

3 ответа

Решение

Я не уверен, если 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)


1-й пример запроса SQL-2

Поиск узлов cq:PageContent с * в любом атрибуте. % (Знак процента) является символом подстановки. * Ищется.

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

2-й пример запроса SQL-2

Поиск узлов cq:PageContent с% в любом атрибуте. Поэтому знак процента экранируется символом \% (и окружен символом подстановки%).

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

3-й пример XPath Query

Почти так же, как последний, так же, как запрос XPath. Только я просто не знаю, как можно искать любой атрибут. Таким образом, этот пример ищет атрибуты jcr:title.

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

В вашей документации есть ответ. Существуют специальные символы, которые вы должны экранировать, но если вы хотите, чтобы что-то буквальное, такое как звездочка, соответствовало только символу '*', вы должны использовать escape-символ, который является обратной косой чертой. Документация утверждает, что это немного сбивает с толку, так это то, что сама по себе обратная косая черта является специальным символом при разборе строки, поэтому, если вы хотите, чтобы обратная косая черта рассматривалась как escape-символ, вам нужно ее экранировать.

Другими словами, чтобы избежать звездочки, нужно записать ее как

\\*

Я наконец-то нашел ответ на вики-странице Jackrabbit

Экранирование текста в полнотекстовых (содержит) предложения

Дуб Jackrabbit использует грамматику Apache Lucene для полнотекстового поиска. Таким образом, чтобы избежать пользовательского текста для использования в контейнерах, вам необходимо либо отфильтровать все специальные символы, либо экранировать их. Так, например, чтобы отфильтровать специальные символы, используйте:

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: содержит (...) (см. также JCR-1248):

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

Другие вопросы по тегам