ボクココ

個人開発に関するテックブログ

Elasticsearch のクエリとフィルタについて

ども、@kimihomです。

今回は Elasticsearch の Query と Filter について自分の理解した範囲で書いてみることにする。

クエリ と フィルタ の違い

本家の英語ドキュメントを読むと、以下のように書かれている。

As a general rule, use query clauses for full-text search or for any condition that should affect the relevance score, and use filter clauses for everything else.

軽く訳すと、一般的なルールとして、フルテキスト検索か関連するスコアに影響する条件があるときは クエリ を使い、それ以外はフィルタを使う。 とある。どの程度、検索結果に関連性が高いかを示すスコアが大事な時は query を使うという感じか。普通の LIKE 検索程度だったら filter でも大丈夫なようだ。

この違いを知っておくと、割と Elasticsearch で投げる構文を理解しやすかった。

検索のサンプル

まずはデータを投入しよう。 Kibana にある Sense ってのをプラグインとしてインストールすると、実験が色々できて理解が深まった。 Kibana の Zip を本家サイトからDLし、以下のプラグインを入れるコマンドを打つことで導入できる。

$./bin/kibana plugin --install elastic/sense
./bin/kibana

# Server running at http://0.0.0.0:5601 ...

まずはデータ投入。

# Insert some example docs
PUT /test/test/1
{
  "folder": "inbox",
  "email": "Big opportunity"
}

PUT /test/test/2
{
  "folder": "spam",
  "email": "Business opportunity"
}

PUT /test/test/3
{
  "folder": "inbox",
  "email": "Urgent business proposal"
}

これらをフィルタとクエリでいろいろな条件で取ってくるとする。

すべて取得

この時はクエリしか使わないので、トップに query と指定してその直下に条件を書くだけで良い。

GET /_search
{
    "query": {
        "match_all": {}
    }
}

この場合 インデックス と タイプ を指定していないので、Elasticsearch に保存したすべてのデータを取ってくることになる。限定したい場合は GET /index/_search とか、 GET /index/type/_search などのようにパスで区切って限定できる。てか GET にリクエストボディを入れてリクエストを送るってのがなかなか新鮮。普通のHTTPのGETとかだとやらないやり方だ。

ただ、冗長だけどこうやってかけることも知っておくといいと思った。

GET /_search
{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      }
    }
  }
}

それはこの後書く フィルタ と組み合わせる時に必要な書き方である。

クエリとフィルタでの取得

さて、上記データでクエリとフィルタ合わせ技はこんな感じになる。

GET /_search
{
  "query": {
    "filtered": {
      "query": {
        "match": {
          "email": "business opportunity"
        }
      },
      "filter": {
        "term": {
          "folder": "inbox"
        }
      }
    }
  }
}

クエリの match は businessopportunity があればヒットするけど、 フィルタの term は一致してないとヒットしない。クエリとフィルタを合わせ技で書くときは、クエリの指定は query.filtered.query のように query が2回出てくることになるようだ。ここら辺が初心者にはちょっと気持ち悪かったけど、慣れなのかな。

終わりに

今回はめちゃめちゃシンプルなところだけ書いてみた。もっと細かい指定ができるけど、この基本さえ押さえておけば、あとは他の種類を知るだけなので入り口の記事としては有用かと思う。

本家ドキュメントが割とボリュームあって読み終えるには時間がかかりそうだが、じっくりとブログに理解したことを書きながら読み進めようと思う。