Elasticsearch(2.4)のQuery一覧 ~その2~

# ElasticsearchのQuery一覧
「[その１](http://qiita.com/gdmiwasawa/items/8063d71d46962f775b04)」に続いて「その２」。同じく[ドキュメント](https://www.elastic.co/guide/en/elasticsearch/reference/current/term-level-queries.html)をもとに簡単に説明していきます。
今回は実際にQueryを実行していきます！
インデックスはこんな感じ

```json:PUT_test/user/1
{
  "name": "suzuki",
  "age" : 28,
  "male": false,
  "description": "I am a pen."
}
```
```json:PUT_test/user/2
{
  "name": "tanaka",
  "age": 25,
  "male": true,
  "description": "null"
}
```
```json:PUT_test/user/3
{
  "name": "satou",
  "age": 22,
  "male": true
}
```

# Term level queries
```Full Text Query```と違い、検索するQueryはAnalyzeされません。そのため、数字や日付に対して有効なQueryが多いです。

## Term Query
完全一致したドキュメントがマッチするQuery。
数字や日付に加えて、boolean、テキストにも使う。
検索時にフィルタリングしたい時に```post_filter```に入れて使うことが多い。（使用例では```query```で使っています）
登録項目の定型テキスト（都道府県）等にも使ったりする。（このように使うためには、フィールドの"index"を"not_analyzed"に設定する必要がある。）
###使用例
女性を検索したい時

```json:GET_test/user/_search
{
  "query": {
    "term": {
      "male": {
        "value": "false"
      }
    }
  }
}
```

結果

```json:result1.json
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.30685282,
    "hits": [
      {
        "_index": "test",
        "_type": "user",
        "_id": "1",
        "_score": 0.30685282,
        "_source": {
          "name": "suzuki",
          "age": 28,
          "male": false,
          "description": "I am a pen."
        }
      }
    ]
  }
}
```
女性のユーザのみ取得することができました。

## Terms Query
```Term Query```の複数のQueryで検索(or)できるやつ。
### 使用例
名前が"tanaka"と"suzuki"のユーザを取得するQuery

```json:GET_test/user/_search
{
  "query": {
    "terms": {
      "name": [ "tanaka", "suzuki" ]
    }
  }
}
```
```json:result2.json
{
  "took": 6,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 0.19245009,
    "hits": [
      {
        "_index": "test",
        "_type": "user",
        "_id": "2",
        "_score": 0.19245009,
        "_source": {
          "name": "tanaka",
          "age": 25,
          "male": true
        }
      },
      {
        "_index": "test",
        "_type": "user",
        "_id": "1",
        "_score": 0.19245009,
        "_source": {
          "name": "suzuki",
          "age": 28,
          "male": false,
          "description": "I am a pen."
        }
      }
    ]
  }
}
```
## Range Query
名前の通り範囲を指定できるQuery。
日付とか数字に使う。
日付に使う時はタイムゾーンを指定したりもできる。また、日付の代わりに"now"を指定することで、現在の時刻を指定することができる。（便利）

###使用例
年齢が22以上25以下のユーザを検索する。

```json:GET_test/user/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 22,
        "lte": 25
      }
    }
  }
}
```
```json:result3.json
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "test",
        "_type": "user",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "tanaka",
          "age": 25,
          "male": true
        }
      },
      {
        "_index": "test",
        "_type": "user",
        "_id": "3",
        "_score": 1,
        "_source": {
          "name": "satou",
          "age": 22,
          "male": true
        }
      }
    ]
  }
}
```
gte,lteの片方だけを指定できたり、イコールを含めたくない場合にはgt,ltを使ったりする。
## Exists Query
指定したフィールドを持っているもののみを絞り込めるQuery。
値がnullのものは含まれない。
逆に指定したフィールドを持っていないもののみを絞り込みたいときは```Bool Query```の```must_not```を使う。

### 使用例
descriptionを登録しているユーザのみを検索

```json:GET_test/user/_search
{
  "query": {
    "exists": {
      "field": "description"
    }
  }
}
```
```json:result4.json
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 1,
    "hits": [
      {
        "_index": "test",
        "_type": "user",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name": "suzuki",
          "age": 28,
          "male": false,
          "description": "I am a pen."
        }
      }
    ]
  }
}
```
## Wildcard Query
Queryに"*"と"?"が使える。
使ったことない。
### 使用例
nameに「a」がふくまれているユーザのみを検索

```json:GET_test/user/_search
{
  "query": {
    "wildcard": {
      "name": {
        "value": "*a*"
      }
    }
  }
}
```
```json:result5.json
{
  "took": 14,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "test",
        "_type": "user",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "tanaka",
          "age": 25,
          "male": true,
          "description": null
        }
      },
      {
        "_index": "test",
        "_type": "user",
        "_id": "3",
        "_score": 1,
        "_source": {
          "name": "satou",
          "age": 22,
          "male": true
        }
      }
    ]
  }
}
```
## Regexp Query
正規表現を使用できるQuery。
```Wildcard Query```と同様に使えるので、使用例は省略。

## Fuzzy Query
曖昧な単語用のQuery。
レーベンシュタイン距離を元に類似度を計算している。（内容知らない）
stringのフィールド以外にも日付や数字にもつかえる。
stringで使うことが多い。
パラメータの```fuzziness```でどのくらいの類似性を許容するかを設定できる（詳しくは[ここ](https://www.elastic.co/guide/en/elasticsearch/reference/current/common-options.html#fuzziness)）。
Term level queriesの中でこのQueryだけ、フィルターではなくクエリーとして流すことが多い。

###　使用例
名前が"tana"に近い人を検索

```json:GET_test/user/_search
{
  "query": {
    "fuzzy": {
      "name": {
        "value": "tana",
        "fuzziness": 2
      }
    }
  }
}
```
```json:result5.json
{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 1,
    "max_score": 0.30685282,
    "hits": [
      {
        "_index": "test",
        "_type": "user",
        "_id": "2",
        "_score": 0.30685282,
        "_source": {
          "name": "tanaka",
          "age": 25,
          "male": true
        }
      }
    ]
  }
}
```
fuzzinessを設定しない（デフォルト値のAUTO）にすると何もヒットしない。

## Type Query
Typeが等しいものを取得するQuery。
document名/type名/searchを使えばtypeの絞りこみはできるので、用途がわからない。
用途わかる方コメントください。

### 使用例
typeがuserのものを検索

```json:GET_user/_search
{
  "query": {
    "type": {
      "value": "user"
    }
  }
}
```
```json:result6.json
{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 1,
    "hits": [
      {
        "_index": "test",
        "_type": "user",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "tanaka",
          "age": 25,
          "male": true,
          "description": null
        }
      },
      {
        "_index": "test",
        "_type": "user",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name": "suzuki",
          "age": 28,
          "male": false,
          "description": "I am a pen."
        }
      },
      {
        "_index": "test",
        "_type": "user",
        "_id": "3",
        "_score": 1,
        "_source": {
          "name": "satou",
          "age": 22,
          "male": true
        }
      }
    ]
  }
}
```
今、別typeのもの作ってないので、すべて表示されます。

## Ids Query
idを複数指定するためのQuery。
一つの場合は```GET document名/type名/id```で取得できるので使わない。
検索から除外したいidを指定するしたり、idの一覧の中から検索したいときによく使う。

###使用例
idが1と３のユーザを取得

```json:GET_test/_search
{
  "query": {
    "ids": {
      "values": [1, 3]
    }
  }
}
```
```json:result7.json
{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 1,
    "hits": [
      {
        "_index": "test",
        "_type": "user",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name": "suzuki",
          "age": 28,
          "male": false,
          "description": "I am a pen."
        }
      },
      {
        "_index": "test",
        "_type": "user",
        "_id": "3",
        "_score": 1,
        "_source": {
          "name": "satou",
          "age": 22,
          "male": true
        }
      }
    ]
  }
}
```

#まとめ
今回は、Queryの書き方も紹介してみましたがいかがだったでしょうか？
SQLに書き換えられるようなものも多く多かったと思います。
他にもこういう使い方があるよとか、こういうことも書いて欲しいとかありましたら、コメントしてください。