2009-12-04 3 views
14

Sto tentando di implementare uno Faceted search o tagging con filtro a tag multipli. Nella navigazione a faccette vengono visualizzate solo le categorie non vuote e il numero di elementi nella categoria che corrispondono anche ai criteri già applicati viene presentato tra parentesi.Implementazione efficiente della ricerca a faccette nei database relazionali

I can get all items having assigned categories using INNER JOINs e get number of items in all category using COUNT and GROUP BY, tuttavia non sono sicuro di come verrà ridimensionato a milioni di oggetti e migliaia di tag. Soprattutto il conteggio.

So che ci sono alcune soluzioni non-relazionali come Lucene + SOLR, ma ho trovato anche alcune implementazioni RDBMS basati closed-source che si dice di essere entreprise resistenza come il software FacetMap.com o Endeca, quindi ci deve essere un modo efficiente per eseguire ricerche sfaccettate in database relazionali.

Qualcuno ha esperienza nella ricerca a faccette e potrebbe dare qualche consiglio?

Memorizzare i conteggi per ciascun gruppo di categorie? Forse usare qualche tecnica incrementale intelligente che aggiornerà i contatori?

Edit:

Un esempio di navigazione a faccette può essere trovato qui: Flamenco.

Attualmente ho lo schema standard a 3 tabelle (articoli, tag e items_tags come descritto qui: http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html#toxi) più una tabella per le faccette. Ogni tag ha assegnato un aspetto.

+0

Ti hanno tavoli sono allestiti già? Puoi fornire la struttura? –

+0

Per chiarire, Endeca non è un wrapper su un database relazionale. Memorizza internamente tutte le informazioni necessarie per la ricerca sfaccettata e altre operazioni. –

+0

Il collegamento Flamenco non funziona più. È questo il nuovo? http://flamenco.berkeley.edu/ –

risposta

4

Posso solo confermare quello che dice Nils. RDBMS non sono buoni per la ricerca multidimensionale. Ho lavorato con alcune soluzioni intelligenti, i caching counters, l'uso di trigger e così via. Ma alla fine, l'indicizzatore dedicato esterno vince sempre.

FORSE, se si trasformano i dati in modello dimensionale e lo si alimenta con un OLAP [intendo motore MDX], funzionerà correttamente. Ma sembra una soluzione un po 'troppo pesante, e sicuramente non sarà in tempo reale.

Al contrario, la soluzione con motore di indicizzazione dedicato (pensa che Lucene, pensa Sphinx) può essere reso quasi in tempo reale con aggiornamenti di indice incrementali.

5

IMO, i database relazionali non sono così efficaci nella ricerca. Otterresti prestazioni migliori da un motore di ricerca dedicato (come Solr/Lucene).

0

Per quanto riguarda i conteggi, perché estrarli tramite SQL? Dovrai comunque ripetere il risultato impostato nel tuo codice, quindi perché non fare il tuo conto lì?

Attualmente sto utilizzando questo approccio in un'app di ricerca sfaccettata che sto sviluppando e funziona perfettamente. L'unica parte difficile è impostare il codice in modo che non emetta la sfaccettatura finché non raggiunge un nuovo aspetto. A quel tempo, produci il facet e il numero di righe che hai trovato per esso.

Questo approccio presuppone che si stia ripristinando un elenco di tutti gli elementi corrispondenti e, quindi, più righe con lo stesso aspetto. Quando ordinate questo risultato per sfaccettatura, è semplice ottenere il conteggio nel codice.

+2

Ci possono essere centinaia di migliaia di record corrispondenti, quindi non posso memorizzare il set di risultati in memoria. Sto recuperando solo la prima pagina, ma voglio sapere quanti record dell'intero set di risultati rientrano nelle categorie visualizzate sotto le faccette. –

2

Ricerca sfaccettata è un problema analitico, il che significa che il dimensionamento è una buona scommessa. Aka, la cosa contro cui devi cercare deve essere in forma tabellare.

Includere tutte le colonne di interesse nella tabella analitica.

Inserire valori continui in bucket.

Utilizzare le colonne booleane per "molti" articoli come categorie o tag, ad esempio se ci sono tre tag "foo", "bar" e "baz", si avranno tre colonne booleane.

Utilizzare una vista materializzata per creare la tabella analitica.

Indicizza lo schifo di esso. Alcuni database supportano gli indici per questo tipo di applicazione.

Filtra solo una volta.

Unione i tuoi risultati.

Creare viste materializzate pre-aggregate per domande comuni.

questo articolo potrebbe aiutare anche voi: https://blog.jooq.org/2017/04/20/how-to-calculate-multiple-aggregate-functions-in-a-single-query/

with filtered as (
    select 
    * 
    from cars_analytic 
    where 
     [some search conditions] 
) 

--for each facet: 

select 
    'brand' as facet, 
    brand as value, 
    count(*) as count 
from 
    filtered 
group by 
    brand 

union 

select 
    'cool-tag' as facet, 
    'cool-tag'as value, 
    count(*) as count 
from 
    filtered 
where 
    cool_tag 

union 

... 


-- sort at the end 
order by 
    facet, 
    count desc, 
    value 

100.000 record con 5 sfaccettature a ~ 150 ms