2013-04-03 22 views
17

私は3レベル(またはそれ以上)の子 - 親を索引付けする必要があります。 たとえば、レベルは著者、書籍、およびその書籍の文字です。Elasticsearch deeper level親子関係(孫)

ただし、2つ以上のレベルのインデックスを作成すると、has_childクエリとhas_parentクエリとフィルタに問題があります。 シャードが5つある場合、最下位レベル(文字)の「has_parent」クエリまたは2番目のレベル(書籍)のhas_childクエリを実行すると、結果の約5分の1が得られます。

私の推測では、書籍は親のIDによって断片に索引付けされるため、親(著者)と一緒に存在しますが、書籍idのハッシュに基づいて文字が索引付けされます。本が索引付けされた実際の断片と必ずしも一致しません。

これは、同じ著者の本のすべての性格が、必ずしも同じシャードに存在するとは限らないことを意味します。

何か間違っていますか?どのように私はこれを解決することができますか?例えば、著者が「女性のキャラクターと一緒に本を書いたもの」などの複雑なクエリを本当に必要としています。

I怒っで、問題を示す要旨:

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

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

と5つの破片指数、私は "とのクエリを作ることができない:私はマッピングを持っている場合という、 https://gist.github.com/eranid/5299628

ボトムラインでありますhas_child」と "HAS_PARENT"

クエリ:

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

は、文字の約5分の1を返します。

答えて

25

あなたは正しいですが、親子関係は、特定の親の子がすべて親と同じシャードにある場合にのみ機能します。 Elasticsearchは親IDをルーティング値として使用してこれを実現します。 1つのレベルで素晴らしい作品です。しかし、それは第2レベルと連続レベルで壊れます。親/子/孫関係がある場合、親はそのIDに基づいてルーティングされ、子は親ID(作業)に基づいてルーティングされますが、孫は子IDに基づいてルーティングされ、間違った破片で終わります。例でそれを実証するために、我々は3ドキュメントのインデックスを作成しているものとします: - ここで驚き

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は、文書Douglas-Adamsのルーティングを計算する値Douglas-Adamsを使用しています。文書Mostly-Harmlessの場合、Elasticsearchは親がDouglas-Adamsであるとみなして、再度Douglas-Adamsを使用してルーティングを計算します。すべて同じルーティング値は同じシャードを意味します。しかし、文書Arthur-DentのElasticsearchでは、親にはMostly-Harmlessがあるので、値Mostly-Harmlessがルーティングとして使用され、その結果としてArthur-Dentが間違ったシャードになります。

このためのソリューションは、明示的に祖父母のIDに等しい孫のルーティング値を指定することです:おじいちゃんのドキュメントについては

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。私はそれをどのように指定するのですか? – eran

+4

URLのルーティングパラメータを使用しています。ここのルーティングセクションを参照してください - http://www.elasticsearch.org/guide/reference/api/index_/ – imotov

+0

ありがとうございます。ポストデータでこれを何とか指定することはできますか?具体的にはbulk_indexのために、各文書のルーティングを指定したいのですか? – eran

0

を、あなたは_routingとして_idを取得する必要があります。 父のドキュメントについては、_roarentとして_parent(grandpa._id)を使用してください。 子どものドキュメントについては、grandpa._idを_routingとして使用してください。

+0

私のために混乱します。 –