親ドキュメントの再帰的な取得方法について

join datatypeについて質問です。
ドキュメントの親子関係が

  • 子 a → b → c 親

というようになっており、今後も

  • 子 a → b → c → d → e 親

のように増えていくことが考えられる場合に、
その時点でのaの一番上の親(前者であればc, 後者であればe)を
一度で取得するようなことは出来るのでしょうか?

やはりhas_child queryなどを用いて、一番上の親が取得出来るまでループする必要があるのでしょうか?

イメージとしては

PUT my_index
{
  "mappings": {
    "_doc": {
      "properties": {
        "my_join_field": {
          "type": "join",
          "relations": {
            "new": "old" 
          }
        }
      }
    }
  }
}

PUT my_index/_doc/c
{
  "my_join_field": {
    "name": "new"
  }
}

PUT my_index/_doc/b?routing=c
{
  "my_join_field": {
    "name": "old",
    "parent": c
  }
}

PUT my_index/_doc/a?routing=b
{
  "my_join_field": {
    "name": "old",
    "parent": b
  }
}

# 以下のようなクエリでaの親としてcを取得したい
GET my_index/_search
{
  "query": {
    "has_child": { 
      "type": "old",
      "query": {
        "match": {
          "_id": a
        }
      }
    }
  }
}

のようなものを想定しております。

Elasticsearchのバージョンは6.3.1です。

お手数お掛けしますが、ご教授頂ければ幸いです。
よろしくお願い致します。

既にご覧になっているかもしれませんが・・・

https://www.elastic.co/guide/en/elasticsearch/reference/current/parent-join.html#_multiple_levels_of_parent_join

Using multiple levels of relations to replicate a relational model is not recommended.

親を、とあるので、has_parentなのかな?と思い、読みかえました。

https://www.elastic.co/guide/en/elasticsearch/reference/7.0/query-dsl-has-parent-query.html

Note that the has_parent is a slow query compared to other queries in the query dsl due to the fact that it performs a join. The performance degrades as the number of matching parent documents increases. If you care about query performance you should not use this query.

と書かれており、推奨しないわ、使うとSlow Queryになるわでいいことありません。
Discussの英語の方でも「RDBMSじゃないのだから、非正規化を検討してはどうだ」とあります。
背景も制約も分からないので、まずは非正規化のアプローチが良いと思いますが、
既に検討済みでしたらすみません。

お返事遅くなり申し訳ありません。
has_parentクエリのドキュメントを読んだところ、

This query returns child documents which associated parents have matched.

とありますので、マッチした親ドキュメントに紐づく子のドキュメントを取得するようです。
今回は子のidを指定して、マッチした子ドキュメントに紐づく親のドキュメントを取得したいため、
has_childを使用したいと思っております。

上で記載して頂いたように、推奨されておらず、Slow Queryになってしまうようですので、
フィールドにparentなるものを用意し、

PUT my_index/_doc/a
{
  "parent": "b"
}

PUT my_index/_doc/b
{
  "parent": "c"
}

のように保持して、ループ処理で1つ上の親を順番に取得するようにしようかと思います。

ご回答ありがとうございました :bowing_man:

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.