Jackrabbit リポジトリのオブジェクトにタグを付けました (実際には Adobe/Day CQ の CRX ですが、これは Jackrabbit コードだと思います):
- アセット: タグ = A、B
- 子アセット データ 1: タグ = A、C、E
- 子アセット データ 2: タグ = D、E
親アセットの一連のタグと 1 つの子の結合に対してクエリを実行したい。つまり、"BC" は親と子 1 にあるためアセットに一致しますが、"C D" は組み合わせがないため一致しません。これは、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')
しかしSELECT DISTINCT
、JCR-SQL2 にはありません。代わりに「BE」を検索すると、このアセットが 2 回返されます。これは、asset+child1 と asset+child2 の両方に一致するためです。
どちらのクエリ結果も Java で後処理できます。つまり、最初のケースでは偽陽性の一致を除外するか、2 番目のケースでは重複した結果を除外しますが、これがページングのパフォーマンスにどのように影響するか心配です。より多くのノードをスキャンする必要があります。悪いノードを取り除く必要がなく、ページングの正しい結果サイズを計算するためにロットをスキャンする必要があります。これは、2 番目の SQL2 のケースでは安くなるはずです。なぜなら、検索が順序付けられている場合、ノード パスのみに基づいて重複を見つけることができ、すべての重複が連続しているため、特定のページの価値のあるデータを安価なスキャンだけで見つけることができるため、うまくいけば読み取らずに済むからです。各結果のノード全体ですが、単純なパスのみの場合でも、ページング カウントのすべての結果をスキャンするコストはわかりません。
私たちが検討したさらに別のオプションは、タグを単一のノードに非正規化することです。この場合、検索を正確に保つには、各子ノードに新しい combined_tags 属性を作成し、一連の子ノードに対してのみすべての検索を実行する必要があります。ただし、これには、同じアセットの下にある 2 つの子ノードを一致させると、明確な問題が残ります。
提案をありがとう。これはすでに大規模なインスタンスであり、さらにスケーリングする必要があります。ModeShape は JCR 実装であるという他の質問を見てきましたが、SELECT DISTINCT
ModeShape で CQ をホストすることが実際に可能である場合、そのためだけに ModeShape に切り替えることは最後の手段である必要があると思います。
ここで思いついたアイデアの 1 つは、アセット タグと子タグの各結合を計算し、タグを 1 つの文字列に結合してから、各値をアセットの多値プロパティとして書き込むことです。つまり、asset + child1 = "ABC E" です。アセット + child2 = "ABD E" であるため、次のようになります。
- アセット: タグ = A、B; tagUnions = "ABC E", "ABD E"
タグを文字列に結合する固定順序 (アルファベット順など) を定義している限り、任意の組み合わせを検索できますtagUnions LIKE '%B%C%'
(ただし、実際にはタグ間に適切な区切り記号を使用します)。これは私たちが見ることができる限り機能しますが、私はあまり好きではありません: アセット + 子ごとに多数のタグが存在する可能性があり、すべてのタグが 1 文字よりも長い名前を持つため、最終的LIKE
にはすべてに対してクエリを実行する長い文字列になります。効率的にインデックスを作成できない可能性があります。
これに対するもう 1 つの方法は、ビットマスクを作成することです。A=1、B=2 などを定義して、ここに多値整数配列を格納し、ビットごとの比較を実行します。ただし、それはおそらく 64 の異なるタグに制限されており、1,000 以上あるので、これを行うことはできないと思います。
そのため、私はまだ、これに対するクリーンなデータベースのようなソリューションを探しています。あなたは私が立てた賞金を逃しましたが、まだダニ、投票、そして助けに対する感謝があります.