# Nested内のオブジェクト数で絞り込みする方法について

**URL:** <https://discuss.elastic.co/t/nested/207430>\
**Category:** 日本語による質問・議論はこちら\
**Created:** [November 12, 2019, 2:13am UTC](https://discuss.elastic.co/t/nested/207430 "2019-11-12T02:13:32Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![onorioriori](https://avatars.discourse-cdn.com/v4/letter/o/74df32/32.png) [@onorioriori](https://discuss.elastic.co/u/onorioriori)\
**Post date:** [November 12, 2019, 2:13am UTC](https://discuss.elastic.co/t/nested/207430/1 "2019-11-12T02:13:32Z")

</div>

お世話になっております。  
以前質問させて頂いた「Nested内のオブジェクト数でソートする方法について」の延長上にあるのですが、

> [@Nested内のオブジェクト数でソートする方法について](https://discuss.elastic.co/t/nested/205971/4):
>
> [https://www.elastic.co/guide/en/elasticsearch/reference/current//search-request-body.html#request-body-search-script-fields](https://www.elastic.co/guide/en/elasticsearch/reference/current//search-request-body.html#request-body-search-script-fields) によりますと、 Using \_source is very slow. と、書かれています。 要素の数でソートしたい、という要件を満たすのであれば、 データ投入時に、その値を別フィールドに保持しておき、そのフィールドでソートする方が、よりシンプルかと思います。 例） PUT my\_index/\_doc/2 { "user\_count": 2, "user" : [{ "first" : "John", "last" : "Smith" }, { "first" : "Alice", "last" : "White" }] }

以下のようなnestedフィールドのインデックスを作成し、

```auto
PUT my_index
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested" 
      }
    }
  }
}

```

nested内のオブジェクト数が1,2,3となるようにドキュメントを入れた際に、

```auto
PUT my_index/_doc/1
{
  "user" : [
    {
      "first" : "John",
      "last" : "Smith"
    }
  ]
}

```

```auto
PUT my_index/_doc/2
{
  "user" : [
    {
      "first" : "John",
      "last" : "Smith"
    },
    {
      "first" : "Alice",
      "last" : "White"
    }
  ]
}

```

```auto
PUT my_index/_doc/3
{
  "user" : [
    {
      "first" : "John",
      "last" : "Smith"
    },
    {
      "first" : "Alice",
      "last" : "White"
    },
    {
      "first" : "hoge",
      "last" : "fuga"
    }
  ]
}

```

これらをuserフィールド内のオブジェクト数で絞って取得することは可能でしょうか？  
ex. オブジェクト数が2つ以上のドキュメントを取得する

script queryを用いて試しているのですが、なかなか取得出来ず苦戦しております。  
※Elasticsearchのバージョンは6.5になります

お手数をおかけしますが、もし方法がありましたらご教示頂ければ幸いです。  
以上、よろしくお願い致します。

---

<div class="post-metadata">

**Author:** ![tsgkdt](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/tsgkdt/32/39151_2.png) [@tsgkdt](https://discuss.elastic.co/u/tsgkdt)\
**Post date:** [November 12, 2019, 4:44am UTC](https://discuss.elastic.co/t/nested/207430/2 "2019-11-12T04:44:42Z")

</div>

Script Queryで頑張ろうとするのは少々しんどそうでしたので、代わりの案を紹介したいです。

> [@Access nested array objects in script query](https://discuss.elastic.co/t/access-nested-array-objects-in-script-query/168461/2):
>
> Have you thought of using an ingest processor that checks the value height and width at index time and stores the result in another field? Then you would have fast queries as you do not need to run an expensive script query at all. Of course this only makes sense if you have a limited number of such checks. --Alex

似たような例がありました。  
[@spinscale](https://discuss.elastic.co/u/spinscale) さんがいうには、オブジェクト数ならオブジェクト数を別フィールドに格納しておけば、より速いクエリが使えるし、コストの高いクエリ（＝Scriptクエリ）を使う必要はない、と書かれています。

今回の例ですと、このようにアプローチするのはダメでしょうか？

↓ userオブジェクト部分の数え上げと、別フィールドに値を格納するパイプラインを作成

```auto
PUT _ingest/pipeline/my_pipeline
{
    "description": "count user nested object size",
    "processors": [
      {
        "script": {
          "source": """
            if (ctx.user != null) {
              ctx.user_count = ctx.user.size();  
            }
            
          """
        }
      }
    ]
}

```

ドキュメント登録時に、パイプラインを指定して登録する。

```auto
PUT my_index/_doc/1?pipeline=my_pipeline
{
  "user" : [
    {
      "first" : "John",
      "last" : "Smith"
    }
  ]
}

```

作成されるIndexで、user\_countにuserオブジェクトの数（今回は１）が入る。

```auto
{
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "user_count" : 1,
          "user" : [
            {
              "last" : "Smith",
              "first" : "John"
            }
          ]
        }
      }

```

このようにしておけば、単純な単一フィールドに対する数値の検索になるため、検索クエリが簡単に作れるかと思います。

Pipelineを使ってuser\_count部分を追加しているのは、既存のデータ投入部分に大きな変更を入れなくてもよくて、Pipelineを指定するだけの変更でできそう、ということをお伝えしたかったためです。

ご参考になれば幸いです。

---

<div class="post-metadata">

**Author:** ![onorioriori](https://avatars.discourse-cdn.com/v4/letter/o/74df32/32.png) [@onorioriori](https://discuss.elastic.co/u/onorioriori)\
**Post date:** [November 14, 2019, 4:55am UTC](https://discuss.elastic.co/t/nested/207430/3 "2019-11-14T04:55:18Z")

</div>

ご回答ありがとうございます。パイプラインというのがあるんですね。  
記載して頂いたようにパイプラインを作成してデータを投入するとuser\_countが入ることが確認出来ました。  
大変参考になりました。

ただ一点問題がありまして、実務上は `user` フィールド以外のフィールドが存在する状態で、  
`user` の配列の要素数が変わることがあり、そのupdate時にパイプラインが使用出来ない点です。  
※インデックスでないとパイプラインを指定出来ないようです

こうした場合ですとやはりuser\_countは自前で入れた方が良さそうですね。

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [December 12, 2019, 4:55am UTC](https://discuss.elastic.co/t/nested/207430/4 "2019-12-12T04:55:18Z")

</div>

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