LoginSignup
15
18

More than 5 years have passed since last update.

ElasticsearchでNested Objectを試す

Last updated at Posted at 2016-08-31

Elasticsearchのドキュメント内にあった、Nested Objectsを実際に、senseで実行します。

indexの作成

PUT /my_index
{
  "mappings": {
    "blogpost": {
      "properties": {
        "comments": {
          "type": "nested", 
          "properties": {
            "name":    { "type": "string"  },
            "comment": { "type": "string"  },
            "age":     { "type": "short"   },
            "stars":   { "type": "short"   },
            "date":    { "type": "date"    }
          }
        }
      }
    }
  }
}

データ挿入

PUT /my_index/blogpost/1
{
  "title": "Nest eggs",
  "body":  "Making your money work...",
  "tags":  [ "cash", "shares" ],
  "comments": [ 
    {
      "name":    "John Smith",
      "comment": "Great article",
      "age":     28,
      "stars":   4,
      "date":    "2014-09-01"
    },
    {
      "name":    "Alice White",
      "comment": "More like this please",
      "age":     31,
      "stars":   5,
      "date":    "2014-10-22"
    }
  ]
}

PUT /my_index/blogpost/2
{
  "title": "Investment secrets",
  "body":  "What they don't tell you ...",
  "tags":  [ "shares", "equities" ],
  "comments": [
    {
      "name":    "Mary Brown",
      "comment": "Lies, lies, lies",
      "age":     42,
      "stars":   1,
      "date":    "2014-10-18"
    },
    {
      "name":    "John Smith",
      "comment": "You're making it up!",
      "age":     28,
      "stars":   2,
      "date":    "2014-10-16"
    }
  ]
}

検索

ブログのタイトルがeggsが含まれており、johnという名前の含まれた28歳がコメントしたものを検索します。Array Objectと違って、どちらも満たしていないと検索結果に現れません。

# クエリ
GET /my_index/blogpost/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "title": "eggs" 
          }
        },
        {
          "nested": {
            "path": "comments", 
            "query": {
              "bool": {
                "must": [ 
                  {
                    "match": {
                      "comments.name": "john"
                    }
                  },
                  {
                    "match": {
                      "comments.age": 28
                    }
                  }
                ]
              }
            }
          }
        }
      ]
}}}

# 結果
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1.8257527,
    "hits": [
      {
        "_index": "my_index",
        "_type": "blogpost",
        "_id": "1",
        "_score": 1.8257527,
        "_source": {
          "title": "Nest eggs",
          "body": "Making your money work...",
          "tags": [
            "cash",
            "shares"
          ],
          "comments": [
            {
              "name": "John Smith",
              "comment": "Great article",
              "age": 28,
              "stars": 4,
              "date": "2014-09-01"
            },
            {
              "name": "Alice White",
              "comment": "More like this please",
              "age": 31,
              "stars": 5,
              "date": "2014-10-22"
            }
          ]
        }
      }
    ]
  }
}

ソートも試しています。

GET /my_index/blogpost/_search
{
  "query": {
    "nested": { 
      "path": "comments",
      "filter": {
        "range": {
          "comments.date": {
            "gte": "2014-10-01",
            "lt":  "2014-11-01"
          }
        }
      }
    }
  },
  "sort": {
    "comments.stars": { 
      "order": "asc",   
      "mode":  "min",   
      "nested_filter": { 
        "range": {
          "comments.date": {
            "gte": "2014-10-01",
            "lt":  "2014-11-01"
          }
        }
      }
    }
  }
}

Aggregation

コメントの平均スター数を月別に取得します。

# クエリ
GET /my_index/blogpost/_search
{
  "size" : 0,
  "aggs": {
    "comments": { 
      "nested": {
        "path": "comments"
      },
      "aggs": {
        "by_month": {
          "date_histogram": { 
            "field":    "comments.date",
            "interval": "month",
            "format":   "yyyy-MM"
          },
          "aggs": {
            "avg_stars": {
              "avg": { 
                "field": "comments.stars"
              }
            }
          }
        }
      }
    }
  }
}

# 結果
{
  "took": 20,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "comments": {
      "doc_count": 4,
      "by_month": {
        "buckets": [
          {
            "key_as_string": "2014-09",
            "key": 1409529600000,
            "doc_count": 1,
            "avg_stars": {
              "value": 4
            }
          },
          {
            "key_as_string": "2014-10",
            "key": 1412121600000,
            "doc_count": 3,
            "avg_stars": {
              "value": 2.6666666666666665
            }
          }
        ]
      }
    }
  }
}

reverse_nested Aggregation

ネスト検索された結果に対して、ネストされているフィールドの外側(今回だと、tags)の集計を取得できる。

# クエリ
GET /my_index/blogpost/_search
{
  "size" : 0,
  "aggs": {
    "comments": {
      "nested": { 
        "path": "comments"
      },
      "aggs": {
        "age_group": {
          "histogram": { 
            "field":    "comments.age",
            "interval": 10
          },
          "aggs": {
            "blogposts": {
              "reverse_nested": {}, 
              "aggs": {
                "tags": {
                  "terms": { 
                    "field": "tags"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

# 結果
{
  "took": 8,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "comments": {
      "doc_count": 4,
      "age_group": {
        "buckets": [
          {
            "key": 20,
            "doc_count": 2,
            "blogposts": {
              "doc_count": 2,
              "tags": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                  {
                    "key": "shares",
                    "doc_count": 2
                  },
                  {
                    "key": "cash",
                    "doc_count": 1
                  },
                  {
                    "key": "equities",
                    "doc_count": 1
                  }
                ]
              }
            }
          },
          {
            "key": 30,
            "doc_count": 1,
            "blogposts": {
              "doc_count": 1,
              "tags": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                  {
                    "key": "cash",
                    "doc_count": 1
                  },
                  {
                    "key": "shares",
                    "doc_count": 1
                  }
                ]
              }
            }
          },
          {
            "key": 40,
            "doc_count": 1,
            "blogposts": {
              "doc_count": 1,
              "tags": {
                "doc_count_error_upper_bound": 0,
                "sum_other_doc_count": 0,
                "buckets": [
                  {
                    "key": "equities",
                    "doc_count": 1
                  },
                  {
                    "key": "shares",
                    "doc_count": 1
                  }
                ]
              }
            }
          }
        ]
      }
    }
  }
}

参考

15
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
18