Я помеченные объекты в хранилище Jackrabbit (на самом деле CRX Adobe/день Cq, но я думаю, что это код Jackrabbit):поиски Jackrabbit через соединяемые узлы
- актива: теги = A, B
- ребенок данных активов 1: теги = A, C, E
- данные ребенка активов 2: теги = D, E
Я хочу д uery против объединения набора тегов родительского актива и одного дочернего элемента, то есть «BC» будет соответствовать активу, потому что у нас есть те, что находятся в родительском и дочернем 1, но «CD» не будет соответствовать, потому что нет никакой комбинации родительского и одного child, который соответствует этому, поскольку 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, потому что, если мой запрос упорядочен, я могу обнаружить дубликаты на основе пути узла, и все дубликаты будут последовательными, поэтому я могу найти данные, данные по данной странице с дешевым сканированием, только надеемся, без чтения весь узел для каждого результата, но я не знаю, сколько стоит сканирование всех результатов для счета подкачки, даже для простого случая только для путей.
Еще один вариант, который мы рассмотрели, является денормализацией тегов в одном узле. В этом случае, чтобы сохранить точность поиска, это должно было бы означать создание нового атрибута comb_tags в каждом дочернем узле и выполнение всех поисков только с набором дочерних узлов. Однако это все еще страдает от отдельной проблемы, если мы сопоставим два дочерних узла под одним и тем же активом.
Спасибо за любые предложения. Это уже большой экземпляр, и его необходимо будет масштабировать. Я видел другие вопросы, которые говорят, что ModeShape - это реализация JCR, которая имеет SELECT DISTINCT
, но я думаю, что переход на ModeShape только для этого должен быть последним, если действительно можно разместить CQ в ModeShape.
Одна идеи, которую мы придумали сейчас, чтобы вычислить каждое объединение тегов активов и дочерние тегов и объединить тег в одну строку, а затем записать каждое значение в качестве многозначного свойства актива, т.е.актив + ребенок1 = «A B C E» и актив + ребенок2 = «A B D E», поэтому мы получаем
- актив: теги = A, B; tagUnions = «ABCE», «ABDE»
Пока мы определяем фиксированный порядок для объединения тегов в строку (например, в алфавитном порядке) мы можем поиск по любой комбинации с использованием tagUnions LIKE '%B%C%'
(за исключением Я хотел бы использовать соответствующие разделители между тегами в реальном случае). Хотя это будет работать, насколько мы можем видеть, мне это не очень нравится: существует потенциально большое количество тегов на каждый актив + ребенок, все с более длинными именами, чем одиночные буквы, что означает, что мы закончим с длинными строками, выполняющими LIKE
запросов на всех из них, которые, вероятно, не могут быть проиндексированы эффективно.
Другое дело, чтобы сделать битовую маску: определить A = 1, B = 2 и т. Д. И, таким образом, хранить здесь многозначный целочисленный массив, а затем выполнить поразрядное сравнение. Однако это, вероятно, ограничивается 64 различными тегами, и, поскольку мы имеем 1000+, я не думаю, что мы можем это сделать - даже если JCR поддерживает побитовые операции, чего я ожидаю, это не произойдет.
Поэтому я все еще ищу для этого чистое решение, подобное базе данных. Вы пропустили щедрость, которую я приносил, но все же есть тики, голоса и благодарность за любую помощь.
Спасибо. На самом деле это не SQL 'UNION', который мне нужен в терминах объединения соединений по двум запросам, но я вычисляю совпадение с логическим объединением двух свойств между разными узлами, поэтому это SQL' JOIN' и 'SELECT DISTINCT', которые Мне нужно.Решение, которое вы связываете - заказывайте и удаляйте последовательные дубликаты, - это одна из идей, которые я упомянул в параграфе о результатах последующей обработки, и проблема с этим связана с правильной подкачкой: мне нужно будет сканировать все записи до текущего страницу, где начинается страница, и сканировать все, чтобы получить точное количество общих страниц. – Rup
... и система, с которой я работаю, имеет миллионы активов, поэтому 10 000+ результатов из простого запроса не являются неслыханными - я не могу предположить, что у меня есть небольшое количество результатов, поскольку парень говорит, что у него есть это связанное решение. Думаю, мне нужна сортировка базы данных, чтобы получить эффективный пейджинг. В любом случае документы Jackrabbit рекомендуют вам использовать 'ORDER BY' в любом случае, поскольку заказ по умолчанию JCR (если он отключен в файле repository.xml) потенциально дорог для вычисления. – Rup
@Rup Спасибо за обновление. Как вы помните, пост-обработка результатов на Java возможна, но может быть потенциально дорогостоящей, поскольку вы пересекаете дополнительные узлы, которые вы уже посетили. Таким образом, это сводится к вопросу эффективного обхода вашей структуры данных. Hmn. Я должен посмотреть на это позже и вернуться к вам. :) – MrGomez