Jackrabbit搜索加入的节点

时间:2012-03-26 11:49:15

标签: jackrabbit jcr cq5 crx

我在Jackrabbit存储库中标记了对象(实际上是Adobe / Day CQ的CRX,但我认为这是Jackrabbit代码):

  • asset:tags = A,B
    • 子资产数据1:tags = A,C,E
    • 子资产数据2:tags = 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:如果我搜索“B E”,我会将此资产返回两次,因为这会匹配asset + child1和asset + child2。

我可以在Java中对查询结果进行后处理,即筛选出第一种情况的误报匹配或者过滤掉第二种情况的重复结果,但我很担心这会如何影响分页性能:我需要扫描比清除坏节点所需的节点更多的节点,我需要扫描批次以计算正确的分页结果大小。对于第二个SQL2案例,这应该更便宜,因为如果我的搜索是有序的,我可以单独根据节点路径发现重复,并且所有重复都是连续的,所以我只能通过便宜的扫描找到给定页面的数据,但希望无需阅读每个结果的整个节点,但我不知道扫描所有结果的分页计数的成本,即使对于简单的仅路径情况。

我们考虑的另一个选择是将标签非规范化为单个节点。在这种情况下,为了保持搜索准确,这必须意味着在每个子节点中创建一个新的combined_tags属性,并仅对该组子节点执行所有搜索。但是,如果我们匹配同一资产下的两个子节点,这仍然会遇到明显的问题。

感谢您的任何建议。这已经是一个大型实例,需要进一步扩展。我已经看到其他问题,说ModeShape是一个JCR实现,它有SELECT DISTINCT,但我认为仅仅为了那个而转换到ModeShape必须是最后的手段,如果确实可以在ModeShape上托管CQ。


我们现在提出的一个想法是计算资产标签和子标签的每个联合,并将标签组合成一个字符串,然后将每个值写为资产的多值属性,即asset + child1 =“ ABCE“和asset + child2 =”ABDE“,所以我们得到

  • asset:tags = A,B; tagUnions =“A B C E”,“A B D E”

只要我们定义将标签组合成字符串的固定顺序(例如字母),我们就可以使用tagUnions LIKE '%B%C%'搜索任何组合(除了我在实际情况下在标签之间使用适当的分隔符)。虽然这可以在我们看到的情况下工作但我并不喜欢它:每个资产+孩子可能有大量标签,所有名称都比单个字母更长,这意味着我们最终会执行长字符串{{1}查询所有可能无法有效编制索引的查询。

另一种观点是制作一个位掩码:定义A = 1,B = 2等,然后在此处存储一个多值整数数组,然后进行逐位比较。然而,这可能仅限于64个不同的标签,因为我们有1000多个,我不认为我们可以做到这一点 - 即使JCR支持按位操作,我希望它不会。

所以我仍然在寻找一个干净的类似数据库的解决方案。你错过了我提出的赏金,但仍然有任何帮助的投票,投票和感谢。

1 个答案:

答案 0 :(得分:1)

来自the Apache Jackrabbit mailing list

  

是的,不幸的是,不支持联合查询。有关于此的任何工作   区域将非常感激。

     

同时,最好的解决方法可能是做两个单独的查询   并在应用程序代码中显式执行联合   结合两个结果集。

所以,这是一个选择。查看您提供的SQL:

  

但JCR-SQL2中没有SELECT DISTINCT:如果我搜索“B”   E“我会将此资产返回两次,因为这两者都匹配   asset + child1和asset + child2。

我查看了Jackrabbit支持的可能解决方案并空手而归。但是,我同意提出的解决方案here

  

我所做的是用适当的ORDER BYs做一个简单的SELECT ...   然后每次我使用一行,我都知道它与它不一样   上一篇: - )

(Sics保留。)

虽然ORDER BY可能是可疑的,除非您需要数据库支持的排序,是否有什么阻止您在控制器中构建一个哈希集以使用JCR API将结果限制为唯一值?