2013-04-03 20 views
17

Ho bisogno di indicizzare 3 livelli (o più) di genitore figlio. Ad esempio, i livelli potrebbero essere un autore, un libro e caratteri di quel libro.Elasticsearch livello più profondo Relazione genitore-figlio (nipote)

Tuttavia, durante l'indicizzazione di più di due livelli c'è un problema con has_child e has_parent query e filtri. Se ho 5 frammenti, ottengo circa un quinto dei risultati quando si esegue una query "has_parent" al livello più basso (caratteri) o una query has_child al secondo livello (libri).

La mia ipotesi è che un libro venga indicizzato a un frammento dal suo id padre e quindi risiederà insieme al suo genitore (autore), ma un personaggio viene indicizzato a un frammento basato sull'hash dell'ID libro, che fa non è necessariamente conforme al frammento effettivo su cui è stato indicizzato il libro.

E così, questo significa che tutti i caratteri dei libri dello stesso autore non risiedono necessariamente nello stesso frammento (tipo di paralizzare davvero il vantaggio genitore-figlio).

Sto facendo qualcosa di sbagliato? Come posso risolvere questo problema, poiché sono davvero necessario per query complesse come "quali autori hanno scritto libri con personaggi femminili", ad esempio.

ho pazza una sostanza che mostra il problema, a: https://gist.github.com/eranid/5299628

Linea di fondo è, che se ho una mappatura:

"author" : {   
     "properties" : { 
    "name" : { 
     "type" : "string" 
    } 
     } 
    }, 
"book" : {   
     "_parent" : { 
    "type" : "author" 
     }, 
     "properties" : { 
    "title" : { 
     "type" : "string" 
    } 
     } 
    }, 

"character" : {  
     "_parent" : { 
    "type" : "book" 
     }, 
     "properties" : { 
    "name" : { 
     "type" : "string" 
    } 
     } 
    } 

e un indice di 5 frammenti, non posso fare query con " has_child" e "has_parent"

La query:

curl -XPOST 'http://localhost:9200/index1/character/_search?pretty=true' -d '{ 
    "query": { 
    "bool": { 
     "must": [ 
     { 
      "has_parent": { 
      "parent_type": "book", 
      "query": { 
       "match_all": {} 
      } 
      } 
     } 
     ] 
    } 
    } 
}' 

restituisce solo un quinto (circa) dei caratteri.

risposta

25

È corretto, la relazione padre/figlio può funzionare solo quando tutti i figli di un determinato genitore risiedono nello stesso frammento del genitore. Elasticsearch raggiunge questo risultato utilizzando l'id padre come valore di routing. Funziona alla grande su un unico livello. Tuttavia, si rompe sul secondo e sui livelli consecutivi. Quando si ha una relazione genitore/figlio/nipote, i genitori vengono instradati in base al loro id, i figli vengono instradati in base all'id padre (funziona), ma i nipoti vengono instradati in base agli id ​​dei bambini e finiscono in frammenti errati. Per dimostrare su un esempio, supponiamo che stiamo indicizzazione delle 3 documenti:

curl -XPUT localhost:9200/test-idx/author/Douglas-Adams -d '{...}' 
curl -XPUT localhost:9200/test-idx/book/Mostly-Harmless?parent=Douglas-Adams -d '{...}' 
curl -XPUT localhost:9200/test-idx/character/Arthur-Dent?parent=Mostly-Harmless -d '{...}' 

elasticsearch utilizza il valore Douglas-Adams per calcolare l'instradamento del documento Douglas-Adams - nessuna sorpresa qui. Per il documento Mostly-Harmless, Elasticsearch vede che ha il genitore Douglas-Adams, quindi usa nuovamente Douglas-Adams per calcolare il routing e tutto è buono - lo stesso valore di routing indica lo stesso frammento. Ma per il documento Arthur-Dent Elasticsearch vede che ha il genitore Mostly-Harmless, quindi utilizza il valore Mostly-Harmless come routing e come risultato il documento Arthur-Dent finisce nel frammento sbagliato.

La soluzione per questo è di specificare esplicitamente il valore di routing per i nipoti pari al id del nonno:

curl -XPUT localhost:9200/test-idx/author/Douglas-Adams -d '{...}' 
curl -XPUT localhost:9200/test-idx/book/Mostly-Harmless?parent=Douglas-Adams -d '{...}' 
curl -XPUT localhost:9200/test-idx/character/Arthur-Dent?parent=Mostly-Harmless&routing=Douglas-Adams -d '{...}' 
+0

cool. Come posso specificarlo? – eran

+4

utilizzando il parametro di routing sull'URL. Vedi la sezione di routing qui - http://www.elasticsearch.org/guide/reference/api/index_/ – imotov

+0

Grazie. Posso anche specificare questo nei post-dati in qualche modo? in particolare per bulk_index, dove voglio specificare il routing per ogni documento? – eran

0

Per la documentazione nonno, è necessario ottenere il _id come _routing. Per i documenti padre, basta usare _parent (grandpa._id) come _routing. Per i documenti figli, usa semplicemente grandpa._id come _routing.

+0

Confuso per me. –

Problemi correlati