# Object配列内のデータ検索

**URL:** <https://discuss.elastic.co/t/object/104322>\
**Category:** 日本語による質問・議論はこちら\
**Created:** [October 18, 2017, 4:12am UTC](https://discuss.elastic.co/t/object/104322 "2017-10-18T04:12:45Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![drumn](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@drumn](https://discuss.elastic.co/u/drumn)\
**Post date:** [October 18, 2017, 4:12am UTC](https://discuss.elastic.co/t/object/104322/1 "2017-10-18T04:12:45Z")

</div>

ElasticSearchでの開発を始めたばかりの初心者です。

以下のマッピングとデータで、"class"="B"の条件で検索し、  
結果として、"value"内の"string"が"two"と"three"のデータだけを抽出したいのですが、  
方法がわからず、困っております。

マッピングの方法やクエリの組み方について、どのような方法が考えられるのか、  
ご教示いただけないでしょうか。

よろしくお願いいたします。

■マッピング  
{  
"mappings": {  
"testtype": {  
"properties": {  
"name": {  
"type": "keyword"  
},  
"value": {  
"type": "object",  
"properties": {  
"string": {  
"type": "keyword"  
},  
"class": {  
"type": "keyword"  
}  
}  
}  
}  
}  
}  
}

■データ  
{  
"name": "TEST",  
"value": [  
{  
"string": "one",  
"class": "A",  
},  
{  
"string": "two",  
"class": "B",  
},  
{  
"string": "three",  
"class": "B",  
},  
{  
"string": "four",  
"class": "C",  
}  
]  
}

---

<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:** [October 18, 2017, 5:01am UTC](https://discuss.elastic.co/t/object/104322/2 "2017-10-18T05:01:02Z")

</div>

たとえば、次のように1件のindexを作成して、class=Bのものを指定して検索したとき、作成した **レコード** が1件ヒットします。  
このインデックスの中のvalue配列の中からstringがtwo, threeの **要素** だけを取り出したい、ということでしょうか？

### 検索対象レコードの作成

```auto
POST forum1019/testtype/5
{
  "name": "TEST",
  "value": [
    {
      "string": "one",
      "class": "A"
    },
    {
      "string": "two",
      "class": "B"
    },
    {
      "string": "three",
      "class": "B"
    },
    {
      "string": "four",
      "class": "C"
    }
  ]
}

```

## 検索クエリ

これで検索すれば、testtype/5がヒットしますが、value配列の中からclass=Bでない要素を除いておきたい、ということでしょうか？

```auto
GET forum1019/_search
{
  "query": {
    "match": {
      "value.class": "B"
    }
  }
}

```

単純に、class と stringの組み合わせで、class=Bのもののstringだけが欲しいということであれば、  
データを4件として作成すれば良いのではないでしょうか。

```auto
POST forum1019/testtype/1
{
  "name": "TEST",
  "value": {
    "string": "one",
    "class": "A"
  }
}
POST forum1019/testtype/2
{
  "name": "TEST",
  "value": {
    "string": "two",
    "class": "B"
  }
}
POST forum1019/testtype/3
{
  "name": "TEST",
  "value": {
    "string": "three",
    "class": "B"
  }
}
POST forum1019/testtype/4
{
  "name": "TEST",
  "value": {
    "string": "four",
    "class": "C"
  }
}

```

---

<div class="post-metadata">

**Author:** ![drumn](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@drumn](https://discuss.elastic.co/u/drumn)\
**Post date:** [October 18, 2017, 5:18am UTC](https://discuss.elastic.co/t/object/104322/3 "2017-10-18T05:18:46Z")

</div>

早々に返信頂きありがとうございます。

やりたいこととしては、返信いただいた冒頭の部分そのものでございまして、  
ヒットしたvalue配列の中から、stringがtwo, threeの要素だけを取り出したいです。

サンプルとしてデータは1件のみ記載しましたが、このインデックス内には複数件のレコードが存在し、  
かつ、value配列内のデータ数も4つとは限らないというデータ構成になっています。

以上を考慮しまして、良い方法がありましたら、引き続きご教示お願いいたします。

---

<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:** [October 18, 2017, 6:24am UTC](https://discuss.elastic.co/t/object/104322/4 "2017-10-18T06:24:19Z")

</div>

こちらのNested datatypeでお望みの挙動になるのではないでしょうか。  
[https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html](https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html)

こちらで、Mappingの変更、クエリを変更して試した内容を書いておきますので  
期待する内容となっているか確認してみてください。

なお、確認にはkibanaのDev ToolsのConsoleを使っています。

## Mappingの変更

valueのtypeをobjectから **nested** に変更します。

```auto
PUT forum1019
{
  "mappings": {
    "testtype": {
      "properties": {
        "name": {
          "type": "keyword"
        },
        "value": {
          "type": "nested"
        }
      }
    }
  }
}

```

## データの作成

前と変更なし

```auto
POST forum1019/testtype/5
{
  "name": "TEST",
  "value": [
    {
      "string": "one",
      "class": "A"
    },
    {
      "string": "two",
      "class": "B"
    },
    {
      "string": "three",
      "class": "B"
    },
    {
      "string": "four",
      "class": "C"
    }
  ]
}

```

## クエリの変更

nestedを使ったクエリに変更します。  
（\_sourceをfalseにしているのは、便宜的に結果を見やすくするためです）

inner\_hitsをつけておくことで、ヒットした部分だけが抽出されます。

```auto
GET forum1019/_search
{
  "_source": false,
  "query": {
    "nested": {
      "path": "value",
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "value.class": "B"
              }
            }
          ]
        }
      },
      "inner_hits": {}
    }
  }
}

```

## 結果

inner\_hists内を見てください。twoとthreeしか返されていないことが確認できました。

```auto
{
  "took": 14,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.6931472,
    "hits": [
      {
        "_index": "forum1019",
        "_type": "testtype",
        "_id": "5",
        "_score": 0.6931472,
        "inner_hits": {
          "value": {
            "hits": {
              "total": 2,
              "max_score": 0.6931472,
              "hits": [
                {
                  "_nested": {
                    "field": "value",
                    "offset": 2
                  },
                  "_score": 0.6931472,
                  "_source": {
                    "value": {
                      "string": "three",
                      "class": "B"
                    }
                  }
                },
                {
                  "_nested": {
                    "field": "value",
                    "offset": 1
                  },
                  "_score": 0.6931472,
                  "_source": {
                    "value": {
                      "string": "two",
                      "class": "B"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    ]
  }
}

```

---

<div class="post-metadata">

**Author:** ![drumn](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@drumn](https://discuss.elastic.co/u/drumn)\
**Post date:** [October 18, 2017, 6:36am UTC](https://discuss.elastic.co/t/object/104322/5 "2017-10-18T06:36:16Z")

</div>

早々の返信とクエリをご提示頂きありがとうございます。  
返信いただいた内容で、目的の検索が可能になりました。  
本当にありがとうございました！

---

<div class="post-metadata">

**Author:** ![drumn](https://avatars.discourse-cdn.com/v4/letter/d/8edcca/32.png) [@drumn](https://discuss.elastic.co/u/drumn)\
**Post date:** [October 19, 2017, 7:41am UTC](https://discuss.elastic.co/t/object/104322/6 "2017-10-19T07:41:25Z")

</div>

解決した懸案ではありますが、もう１点、ご教示いただきたく思います。

上記の結果を"inner\_hits"を使用せずに取得する方法はあるのでしょうか？

最終的に"inner\_hits"の件数を集計することを考えおりまして、”aggregation”を使ったクエリを組んでみたのですが、  
"[nested] query does not support [aggs]"のエラーで実行できないでおります。

何か方法があるのか、教えていただけるとうれしいです。  
よろしくお願いいたします。

---

<div class="post-metadata">

**Author:** ![johtani](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/johtani/32/44956_2.png) [@johtani](https://discuss.elastic.co/u/johtani)\
**Post date:** [October 25, 2017, 5:54am UTC](https://discuss.elastic.co/t/object/104322/7 "2017-10-25T05:54:32Z")

</div>

[https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-nested-aggregation.html](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-nested-aggregation.html)

こちらではないでしょうか？

---

<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:** [November 22, 2017, 5:54am UTC](https://discuss.elastic.co/t/object/104322/8 "2017-11-22T05:54:35Z")

</div>

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