18

親子の 3 レベル (またはそれ以上) のインデックスを作成する必要があります。たとえば、レベルは、著者、本、およびその本の登場人物である可能性があります。

ただし、2 レベルを超えるインデックスを作成する場合、has_child および has_parent クエリとフィルターに問題があります。シャードが 5 つある場合、最下位レベル (文字) で "has_parent" クエリを実行するか、2 番目のレベル (本) で has_child クエリを実行すると、約 5 分の 1 の結果が得られます。

私の推測では、本はその親 ID によってシャードにインデックス付けされるため、親 (著者) と一緒に存在しますが、キャラクターはブック ID のハッシュに基づいてシャードにインデックス付けされますが、これは必ずしも準拠しているとは限りません。本が索引付けされた実際のシャード。

したがって、これは、同じ著者の本のすべてのキャラクターが必ずしも同じシャードに存在するとは限らないことを意味します (実際には、親子の利点全体を損なうようなものです)。

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

https://gist.github.com/eranid/5299628で、問題を示す要点を作成しました 。

要するに、マッピングがある場合:

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

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

および 5 シャード インデックスでは、"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 (およそ) のみを返します。

4

2 に答える 2

26

親/子関係は、特定の親のすべての子が親と同じシャードに存在する場合にのみ機能します。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のことです。documentMostly-Harmlessの場合、Elasticsearch はそれが parent を持っていることを確認するDouglas-Adamsため、再度使用しDouglas-Adamsてルーティングを計算し、すべてが良好です。同じルーティング値は同じシャードを意味します。しかし、Arthur-DentElasticsearch はドキュメントに parent があることを認識しているMostly-Harmlessため、 valueMostly-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 '{...}'
于 2013-04-03T10:30:02.370 に答える
0

おじいちゃんのドキュメントでは、_id を _routing として取得する必要があります。親ドキュメントの場合は、_parent (grandpa._id) を _routing として使用します。子ドキュメントについては、grandpa._id を _routing として使用してください。

于 2015-03-03T00:05:31.090 に答える