2012-03-26 13 views
6

mi hanno taggato oggetti in un repository Jackrabbit (in realtà di Adobe/Giorno CQ CRX, ma penso che questo è il codice Jackrabbit):ricerche Jackrabbit attraverso nodi uniti

  • patrimoniale: tag = A, B
    • bambino di dati di attività 1: tag = a, C, E
    • dati figlio di attività 2: tag = D, E

voglio q uery contro l'unione di insieme del bene genitore di tag e un bambino, vale a dire "BC" sarebbe partita bene perché abbiamo quelli del genitore e nel bambino 1, ma "CD" non sarebbe partita, perché non c'è nessuna combinazione di genitore e uno figlio che corrisponde a quello perché C e D sono suddivisi su nodi dati figlio separati.

C'è un modo per fare questo in Jackrabbit? Possiamo scrivere una query XPath

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

ma che non funziona perché XPath non sembra garantire che il * uniti asset secondari sono gli stessi, vale a dire questo significa "ogni bambino ha C/D" e così abbinerà il mio bene perché 1+ bambini hanno un C e 1 + i bambini hanno una D. invece ho potuto usare 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') 

ma non c'è SELECT DISTINCT in JCR-SQL2: se invece la ricerca di "BE" Otterrò questa risorsa restituita due volte perché corrisponde sia a asset + child1 che a asset + child2.

Potrei postelaborare sia il risultato della query in Java, ovvero filtrare le corrispondenze false-positive per il primo caso o filtrare i risultati duplicati per il secondo caso, ma sono nervoso su come ciò potrebbe influire sulle prestazioni del paging: avrei bisogno per eseguire la scansione di più nodi del necessario per eliminare i nodi danneggiati, e avrei bisogno di scansionare il lotto per calcolare la dimensione del risultato corretta per il paging. Questo dovrebbe essere più conveniente per il secondo caso SQL2 perché se la mia ricerca è ordinato posso individuare i duplicati in base solo al percorso del nodo e tutti i duplicati saranno consecutivi, in modo da poter trovare la pena di un dato pagina di dati con scansione a buon mercato solo si spera senza leggere l'intero nodo per ogni risultato, ma non conosco il costo di scansionare tutti i risultati per il conteggio delle pagine anche per il caso di solo percorso semplice.

Ancora un'altra opzione che abbiamo considerato è denormalizzare i tag in un unico nodo. In questo caso, per mantenere la ricerca accurata, ciò dovrebbe significare creare un nuovo attributo combined_tags in ogni nodo figlio ed eseguire tutte le ricerche solo sull'insieme di nodi figlio. Tuttavia questo soffre ancora del problema distinto se dovessimo abbinare due nodi figlio sotto la stessa risorsa.

Grazie per eventuali suggerimenti. Questo è già un grande esempio e sarà necessario ridimensionarlo ulteriormente. Ho visto altre domande che dicono ModeShape è un'implementazione di JCR che ha SELECT DISTINCT ma penso che il passaggio a ModeShape solo per questo avrebbe dovuto essere l'ultima risorsa, se davvero è possibile ospitare CQ su ModeShape.


Un'idea che è venuta in mente è ora quello di calcolare ogni unione dei tag attivi e tag di livello inferiore e combinare i tag in una singola stringa quindi scrivere ogni valore come una proprietà multivalore del bene, vale a direasset + child1 = "A B C E" e asset + child2 = "A B D E", quindi otteniamo

  • asset: tag = A, B; tagUnions = "ABCE", "ABDE"

Finché si definisce un ordine fisso per combinare i tag in una stringa (ad esempio alfabetico) possiamo la ricerca di qualsiasi combinazione usando tagUnions LIKE '%B%C%' (tranne userei delimitatori appropriati tra tag nel caso reale). Anche se funzionerà il più possibile, non mi piace molto: ci sono potenzialmente molti numeri di tag per risorsa + figlio, tutti con nomi più lunghi di singole lettere, il che significa che ci ritroveremo con lunghe stringhe che eseguono query LIKE su tutti di loro che probabilmente non possono essere indicizzati in modo efficiente.

Un altro modo per fare questo è creare una maschera di bit: definire A = 1, B = 2 ecc. Quindi memorizzare una serie di numeri interi multivalore e quindi eseguire un confronto bit a bit. Tuttavia questo è probabilmente limitato a 64 tag diversi e poiché abbiamo 1.000+ non credo che possiamo farlo - anche se JCR supporta operazioni bit a bit, cosa che mi aspetterei che non lo fosse.

Quindi sono ancora alla ricerca di una soluzione pulita simile a un database per questo. Ti sei perso la taglia che ho messo, ma ci sono ancora zecche, voti e gratitudine per qualsiasi aiuto.

risposta

1

Da the Apache Jackrabbit mailing list:

Sì, purtroppo le query di unione non sono supportate. Qualsiasi lavoro su quella zona sarebbe molto apprezzato.

Nel frattempo la soluzione migliore consiste probabilmente nel fare due query separate e per eseguire esplicitamente l'unione nel codice dell'applicazione tramite combinando i due gruppi di risultati.

Quindi, questo è fuori come un'opzione. Guardando la SQL che ci hai fornito:

ma non c'è SELECT DISTINCT in JCR-SQL2: se invece la ricerca di "B E" mi metterò questo asset è tornato due volte perché questo corrisponde sia patrimoniale + child1 e risorsa + child2.

Ho esaminato le possibili soluzioni supportate da Jackrabbit e sono venuto a mani vuote. Tuttavia, sono d'accordo con la soluzione presentata here:

Quello che ho fatto è quello di fare un semplice SELECT con sosta ORDINA appropriati ... allora ogni volta che ho usato di fila, ho veried che non è lo stesso come il :-) precedente

(Sics conservato.)

Mentre il ORDER BY è potenzialmente dubbia a meno che non si richiede l'ordinamento del database-backed, c'è qualcosa che impedisce di costruire un hashset nel controllore per limitare i tuoi risultati solo valori univoci che utilizzano l'API JCR?

+0

Grazie. Non è in realtà un 'UNION' SQL di cui ho bisogno in termini di unione di set su due query, ma sto calcolando una corrispondenza con un'unione logica di due proprietà attraverso nodi diversi quindi è un 'JOIN' e' SELECT DISTINCT' SQL che Ho bisogno.La soluzione che colleghi - ordina e rimuovi duplicati consecutivi - è una delle idee che ho menzionato nel paragrafo sui risultati di post-elaborazione, e il problema con questo è il paging giusto: avrei bisogno di scansionare tutti i record fino all'attuale pagina per capire dove inizia effettivamente la pagina e scansionare tutto per ottenere il numero esatto di pagine totali. – Rup

+0

... e il sistema con cui lavoro ha milioni di risorse, quindi non sono inediti oltre 10.000 risultati di una query semplice - Non posso presumere di avere un piccolo numero di risultati come dice il ragazzo che ha quella soluzione collegata. Ho bisogno di un ordinamento basato sul database al fine di ottenere un efficiente paging, penso. In ogni caso i documenti di Jackrabbit consigliano comunque di utilizzare un 'ORDER BY' poiché l'ordine predefinito JCR (a meno che non sia disabilitato in repository.xml) è potenzialmente costoso da calcolare. – Rup

+0

@Rup Grazie per l'aggiornamento. Come accennato, la post-elaborazione dei risultati in Java è possibile, ma può essere potenzialmente costosa quando si attraversano nodi aggiuntivi che altrimenti si sono già visitati. Quindi, si tratta di una traversata efficiente attraverso la struttura dei dati. Hmn. Dovrò guardarlo più tardi e tornare da te. :) – MrGomez

Problemi correlati