Jackrabbit выполняет поиск по присоединенным узлам

Я пометил объекты в репозитории Jackrabbit (на самом деле CRX Adobe/Day CQ, но я думаю, что это код Jackrabbit):

  • актив: теги = 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», я получу этот актив дважды, потому что он соответствует как активу + дочернему элементу1, так и активу + дочернему элементу2.

Я мог бы постобработать любой результат запроса в Java, т.е.отфильтровать ложноположительные совпадения для первого случая или отфильтровать повторяющиеся результаты для второго случая, но я нервничаю, как это повлияет на производительность подкачки: мне нужно будет сканировать больше узлов, чем необходимо, чтобы отсеять плохие узлы, и я потребуется просканировать партию, чтобы вычислить правильный размер результата для пейджинга. Это должно быть дешевле для второго случая SQL2, потому что, если мой поиск упорядочен, я могу обнаружить дубликаты только на основе пути к узлу, и все дубликаты будут последовательными, поэтому я могу найти данные данной страницы с дешевым сканированием, только надеюсь, не читая весь узел для каждого результата, но я не знаю стоимость сканирования всех результатов для подсчета страниц, даже для простого случая только пути.

Еще один вариант, который мы рассмотрели, — денормализация тегов в одном узле. В этом случае, чтобы поиск оставался точным, это должно означать создание нового атрибута Combined_tags в каждом дочернем узле и выполнение всех поисков только по набору дочерних узлов. Однако это по-прежнему страдает от отдельной проблемы, если мы сопоставляем два дочерних узла под одним и тем же активом.

Спасибо за любые предложения. Это уже большой экземпляр, и его необходимо масштабировать дальше. Я видел другие вопросы, в которых говорится, что ModeShape - это реализация JCR, в которой есть SELECT DISTINCT , но я думаю, что переключение на ModeShape только для этого должно быть последним средством, если действительно возможно разместить CQ на ModeShape. .


Одна идея, к которой мы пришли сейчас, состоит в том, чтобы вычислить каждое объединение тегов активов и дочерних тегов и объединить теги в одну строку, а затем записать каждое значение как многозначное свойство актива, т.е. актив + дочерний1 = " ABCE" и актив + дочерний элемент2 = "ABDE", поэтому мы получаем

  • актив: теги = A, B; tagUnions = "A B C E", "A B D E"

Пока мы определяем фиксированный порядок объединения тегов в строку (например, по алфавиту)мы можем искать любую комбинацию, используя tagUnions LIKE '%B%C%'(за исключением того, что в реальном случае я бы использовал правильные разделители между тегами). Пока это будет работать, насколько мы можем видеть, мне это не очень нравится: существует потенциально большое количество тегов на актив + дочерний элемент, все с более длинными именами, чем отдельные буквы, что означает, что мы закончим выполнением длинных строк LIKE запросы ко всем из них, которые, вероятно, не могут быть эффективно проиндексированы.

Другой подход к этому состоит в том, чтобы создать битовую маску: определить A=1, B=2 и т. д. и, таким образом, сохранить здесь многозначный целочисленный массив, а затем выполнить побитовое сравнение. Однако это, вероятно, ограничено 64 различными тегами, и, поскольку у нас есть более 1000, я не думаю, что мы сможем это сделать, даже если JCR поддерживает побитовые операции, чего я ожидаю, не будет.

Так что я все еще ищу чистое решение, похожее на базу данных. Вы пропустили вознаграждение, которое я объявил, но все еще есть галочки, голоса и благодарность за любую помощь.

6
задан Rup 4 April 2012 в 15:28
поделиться