2012-03-26 10 views
6

I Objekte in einem Jackrabbit Repository markiert haben (eigentlich Adobe/Tag CQ CRX, aber ich denke, das ist der Hase-Code ist):Hase sucht über verbundenen Knoten

  • Asset: tags = A, B
    • Kind Asset-Daten 1: tags = A, C, E
    • Kind Asset-Daten 2: tags = D, E

I q wollen Sehr gut gegen die Vereinigung der Tags des Eltern-Assets und eines Kindes, dh "BC" würde dem Asset entsprechen, weil wir diese im Eltern- und Kind-1 haben, aber "CD" würde nicht passen, weil es keine Kombination aus Eltern und Eins gibt Kind, das dem entspricht, da C und D über separate untergeordnete Datenknoten aufgeteilt sind.

Gibt es eine Möglichkeit, dies in Jackrabbit zu tun? Wir können

\\element(*, dam:Asset)[(@tags = 'C' or *\@tags='C') 
         and (@tags = 'D' or *\@tags='D')] 

eine XPath-Abfrage schreiben, aber das wird nicht funktionieren, weil XPath nicht zu garantieren scheint, dass die * Kind Vermögen verbunden gleich sind, dh das bedeutet „jedes Kind hat C/D“ und so weil 1+ Kinder eine C haben meinen Inhalt übereinstimmen und 1+ Kinder haben stattdessen ein D. I 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') 

aber keine SELECT DISTINCT in JCR-SQL2 es verwenden könnte: ich suche nach „BE“, wenn statt Ich werde dieses Asset zweimal zurückgeben, weil es sowohl mit asset + child1 als auch mit asset + child2 übereinstimmt.

Ich könnte entweder Abfrage Ergebnis in Java nachbearbeiten, dh falsch-positive Treffer für den ersten Fall herausfiltern oder doppelte Ergebnisse für den zweiten Fall herausfiltern, aber ich bin nervös, wie dies die Auslagerungsleistung beeinflussen würde: Ich würde brauchen um mehr Knoten als nötig zu scannen, um schlechte Knoten auszusortieren, und ich müsste das Los scannen, um die richtige Ergebnisgröße für den Seitenwechsel zu berechnen. Dies sollte für den zweiten SQL2-Fall billiger sein, denn wenn meine Suche geordnet ist, kann ich Dubletten basierend auf dem Knotenpfad erkennen und alle Duplikate werden konsekutiv sein, so dass ich die Daten einer gegebenen Seite nur mit hoffentlichem Lesen finden kann der gesamte Knoten für jedes Ergebnis, aber ich kenne die Kosten für das Scannen aller Ergebnisse für die Paging-Zählung nicht einmal für den einfachen Nur-Pfad-Fall.

Eine weitere Option, die wir in Betracht gezogen haben, ist die Denormalisierung der Tags in einen einzelnen Knoten. Um in diesem Fall die Suche genau zu halten, müsste dies bedeuten, dass in jedem Kindknoten ein neues combined_tags-Attribut erstellt wird und alle Suchvorgänge nur für die Gruppe der untergeordneten Knoten ausgeführt werden. Allerdings leidet dies immer noch unter dem eindeutigen Problem, sollten zwei untergeordnete Knoten unter dasselbe Asset gestellt werden.

Vielen Dank für Anregungen. Dies ist bereits eine große Instanz und muss weiter skaliert werden. Ich habe andere Fragen gesehen, die sagen, dass ModeShape eine JCR-Implementierung ist, die SELECT DISTINCT hat, aber ich denke, dass der Wechsel zu ModeShape nur der letzte Ausweg wäre, wenn es tatsächlich möglich ist, CQ auf ModeShape zu hosten.


Eine Idee, die wir mit jetzt kommen haben, ist jede Vereinigung der Asset-Tags und Kind-Tags zu berechnen und die Tags in einem einzigen String kombinieren dann jeden Wert als mehrwertige Eigenschaft des Vermögenswertes schreiben, das heißtAsset + child1 = "A B C E" und Asset + child2 = "A B D E", so erhalten wir

  • Asset: tags = A, B; tagUnions = „ABCE“, „ABDE“

Solange wir eine feste Reihenfolge für die Kombination von Tags in einen String (zB alphabetisch) definieren können wir die Suche nach einer beliebigen Kombination tagUnions LIKE '%B%C%' mit (außer ich die richtige Trennzeichen verwenden würde, zwischen Tags im realen Fall). Obwohl das so weit funktioniert, wie wir sehen können, mag ich es nicht wirklich: Es gibt potenziell große Anzahl von Tags pro Asset + Kind, alle mit längeren Namen als einzelne Buchstaben, was bedeutet, dass wir lange Strings haben werden, die LIKE Anfragen ausführen von denen, die wahrscheinlich nicht effizient indiziert werden können.

Eine weitere Möglichkeit ist das Erstellen einer Bitmaske: Definieren Sie A = 1, B = 2 usw. und speichern Sie hier ein mehrwertiges Integer-Array. Führen Sie dann einen bitweisen Vergleich durch. Allerdings ist das wahrscheinlich auf 64 verschiedene Tags beschränkt, und da wir 1.000+ haben, glaube ich nicht, dass wir das schaffen können - selbst wenn JCR bitweise Operationen unterstützt, was ich nicht erwarten würde.

Also bin ich immer noch auf der Suche nach einer sauberen datenbankähnlichen Lösung dafür. Du hast die Kopfgelder vermisst, die ich aufgestellt habe, aber es gibt immer noch Ticks, Stimmen und Dankbarkeit für jede Hilfe.

Antwort

1

Von the Apache Jackrabbit mailing list:

Ja, leider union-Abfragen werden nicht unterstützt. Jede Arbeit auf diesem Bereich würde sehr geschätzt werden.

In der Zwischenzeit ist die beste Problemumgehung wahrscheinlich, zwei separate Abfragen zu tun und die Union im Anwendungscode explizit durch die Kombination der beiden Ergebnismengen durchzuführen.

Also, das ist als eine Option. Mit Blick auf die SQL Sie zur Verfügung gestellt haben:

aber es gibt keine SELECT DISTINCT in JCR-SQL2: wenn ich stattdessen für „B E“ Ich suche diese Anlage zweimal zurück bekommen, weil diese beide Spiele Asset + child1 und Vermögenswert + Kind2.

Ich schaute auf die möglichen Lösungen von Jackrabbit unterstützt und kam mit leeren Händen. Allerdings stimme ich zu, stellte sich mit der Lösung here:

Was ich getan habe ist eine einfache SELECT mit eigneten ORDER BYs zu tun ... dann jedes Mal, wenn ich eine Zeile verwendet, ich veried, dass es nicht das Gleiche als vorherigen :-)

(konserviert Sics.)

Während die ORDER BY möglicherweise fragwürdig ist, wenn Sie Datenbank-backed Sortierung erfordern, ist es Ihnen von Konstruktion eines Hashset in Ihrem Controller zu verhindern, etwas zu begrenzen Ihre Ergebnisse nur zu eindeutige Werte mit der JCR-API?

+0

Danke. Es ist nicht wirklich eine SQL 'UNION', die ich in Bezug auf eine Vereinigungsmenge über zwei Abfragen brauche, aber ich berechne eine Übereinstimmung gegen eine logische Vereinigung zweier Eigenschaften gegenüber verschiedenen Knoten, so dass es ein SQL' JOIN' und 'SELECT DISTINCT' ist Ich brauche.Die Lösung, die Sie verlinken - nach aufeinanderfolgenden Duplikaten sortieren und entfernen - ist eine der Ideen, die ich im Absatz über Post-Processing-Ergebnisse erwähnt habe, und das Problem dabei ist, das Paging richtig zu machen: Ich müsste alle Datensätze bis zur aktuellen scannen Seite, um herauszufinden, wo die Seite tatsächlich beginnt, und scannen Sie alles, um die genaue Anzahl der gesamten Seiten zu erhalten. – Rup

+0

... und das System, mit dem ich arbeite, hat Millionen von Assets, so dass mehr als 10.000 Ergebnisse aus einer einfachen Abfrage nicht unbekannt sind - ich kann nicht davon ausgehen, dass ich eine kleine Anzahl von Ergebnissen habe, wie der Typ sagt diese verknüpfte Lösung. Ich benötige eine datenbankgestützte Sortierung, um effizientes Paging zu erhalten, denke ich. In jedem Fall empfehlen die Jackrabbit-Dokumente, dass Sie sowieso eine ORDER BY-Anweisung verwenden, da die JCR-Standardreihenfolge (sofern sie nicht in der Datei repository.xml deaktiviert ist) möglicherweise sehr teuer zu berechnen ist. – Rup

+0

@Rup Vielen Dank für das Update. Wie Sie bereits erwähnt haben, ist die Nachbearbeitung der Ergebnisse in Java möglich, kann aber möglicherweise kostspielig sein, wenn Sie zusätzliche Knoten durchlaufen, die Sie sonst bereits besucht haben. Es geht also um eine effiziente Durchquerung Ihrer Datenstruktur. Hmn. Ich muss mich später darum kümmern und zu dir zurückkommen. :) – MrGomez