Я отметил объекты в хранилище Jackrabbit (на самом деле это CRX Adobe / Day CQ, но я думаю, что это код Jackrabbit):
- asset: tags = A, B
- данные дочерних активов 1: теги = A, C, E
- данные дочерних активов 2: теги = D, E
Я хочу выполнить запрос кобъединение набора тегов родительского ресурса и одного дочернего элемента, т. е. «BC» будет соответствовать ресурсу, потому что у нас есть те из них, что в родительском и дочернем элементах 1, но «CD» не будет совпадать, поскольку отсутствует комбинация родительского и одного дочернего элементовпотому что C и D разделены между отдельными дочерними узлами данных.
Есть ли способ сделать это в Jackrabbit?Мы можем написать запрос XPath
\\element(*, dam:Asset)[(@tags = 'C' or *\@tags='C')
and (@tags = 'D' or *\@tags='D')]
, но это не сработает, поскольку XPath, похоже, не гарантирует, что присоединенные дочерние активы *
одинаковы, то есть это означает, что "любой дочерний элемент имеет C /D "и так будет соответствовать моему активу, потому что у 1+ детей есть C, а у 1+ детей есть D. Вместо этого я мог бы использовать JCR-SQL2
SELECT * FROM dam:Asset as asset
LEFT OUTER JOIN nt:unstructured as child ON ISCHILDNODE(child,asset)
WHERE (asset.tags = 'C' or child.tags = 'C')
AND (asset.tags = 'D' or child.tags = 'D')
, но в JCR-SQL2 нет SELECT DISTINCT
:если вместо этого я выполню поиск «BE», я получу этот актив дважды, потому что он совпадает с активом + child1 и активом + child2.
Я мог бы постобработать любой результат запроса в Java, то есть отфильтровать ложноположительные совпадения дляв первом случае или отфильтровывать повторяющиеся результаты для второго случая, но я нервничаю, как это повлияет на производительность подкачки: мне нужно отсканировать больше узлов, чем необходимо, чтобы отсеять поврежденные узлы, и мне нужно отсканировать партиювычислить правильный размер результата для подкачки.Это должно быть дешевле для второго случая SQL2, потому что, если мой поиск упорядочен, я могу обнаружить дубликаты на основе только пути к узлу, и все дубликаты будут последовательными, поэтому я могу найти данные данной страницы с помощью дешевого сканирования только, надеюсь, без чтениявесь узел для каждого результата, но я не знаю стоимость сканирования всех результатов для подсчета подкачки, даже для простого случая только для пути.
Еще один вариант, который мы рассмотрели, - это денормализация тегов.в один узел.В этом случае, чтобы обеспечить точный поиск, это должно означать создание нового атрибута комбинированного_круга в каждом дочернем узле и выполнение всех поисков только для набора дочерних узлов.Однако это все еще страдает от отдельной проблемы, если мы сопоставим два дочерних узла под одним и тем же ресурсом.
Спасибо за любые предложения.Это уже большой пример, и его нужно будет масштабировать дальше.Я видел другие вопросы, в которых говорится, что ModeShape является реализацией JCR, которая имеет SELECT DISTINCT
, но я думаю, что переключение на ModeShape только для этого должно быть последним средством, если действительно возможно разместить CQ на ModeShape.
Одна из идей, которую мы пришли сейчас, состоит в том, чтобы вычислить каждое объединение тегов актива и дочерних тегов и объединить теги в одну строку, а затем записать каждое значение как многозначное свойство актива, т.е. asset + child1= "ABCE" и asset + child2 = "ABDE", поэтому мы получаем
- asset: tags = A, B;tagUnions = "ABCE", "ABDE"
Пока мы определяем фиксированный порядок объединения тегов в строку (например, в алфавитном порядке), мы можем искать любую комбинацию, используя tagUnions LIKE '%B%C%'
(кроме Iиспользовать реальные разделители между тегами в реальном случае).Хотя это будет работать, насколько мы можем видеть, мне это не очень нравится: потенциально большое количество тегов на каждый актив + дочерний элемент, все с более длинными именами, чем отдельные буквы, означают, что в итоге мы получим длинные строки, выполняющие запросы LIKE
на всех из них, которые, вероятно, не могут быть эффективно проиндексированы.
Еще один способ сделать это - создать битовую маску: определить A = 1, B = 2 и т. д. и сохранить здесь многозначный целочисленный массив, а затем выполнитьпобитовое сравнение.Однако это, вероятно, ограничено 64 различными тегами, и, поскольку у нас их более 1000, я не думаю, что мы сможем это сделать, даже если JCR поддерживает побитовые операции, чего, как я ожидаю, не будет.
Так что я все еще в поисках чистого решения, похожего на базу данных для этого.Вы пропустили награду, которую я выложил, но все еще есть галочки, голоса и благодарность за любую помощь.