Elastic Search の index(table) を作成して部分 { 一致, 不一致 } 検索をする

kaede_io

kaede

Posted on July 29, 2022

Elastic Search の index(table) を作成して部分 { 一致, 不一致 } 検索をする

why

柔軟に日本語を分解して検索できる Elastic Search を使って
複雑な条件でも自由自在に検索できるようになりたいから。

And, Or, Filter, これらをマスターしたい。

環境構築

アカウント作成してログインするだけなので簡単。
14 日しか使えないけど。

Elastic Search のアカウント作成、ログイン

https://www.elastic.co/guide/en/welcome-to-elastic/current/getting-started-general-purpose.html#gp-gs-prereqs

新規登録すればクラウドトライアルで試しうちできるらしい。
なので登録してログインする

Image description

14 日間使えるらしい。


アプリ作成

Image description

NorthEast1 ( Japan ) を選択して
andOr というアプリ名で作成

クラウドプロバイダーが選択できるので、
ES はプラットフォームではないらしい。

作成されると、UserName と Pass が発行される

ローカルに作らなくても、もうこれでクエリを叩きまくって遊ぶことができる。



コンソールで基礎的な POST / GET を試す

Dev Tools にアクセスしてコンソールを開く

Image description

Java やプラグインは一切追加せずとも

左下の Management / Dev tools にアクセスすれば

Image description

Elastic Search を叩くクエリを書けて
かつ実行できるエディタが開く。


コンソールに新しい index を追加して同時にデータも追加する

https://www.elastic.co/guide/en/welcome-to-elastic/current/getting-started-general-purpose.html#gp-gs-add-data

チュートリアルに従って

POST /customer/_doc/1
{
  "name": "kaede"
}
Enter fullscreen mode Exit fullscreen mode

name: kaede の json を POST で /customer/ の _doc/1 に送ると

POST /customer/_doc/1
{
  "name": "kaede"
}
Enter fullscreen mode Exit fullscreen mode

customer という index (table 相当) が作成され
同時に
Document ID を 1 として name: kaede のデータも登録された。

2, 3 に john, dan, これらの名前のデータも登録した

{
  "_index": "customer",
  "_id": "zAPpVIIB6_QPx1u8MGaH",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 2,
    "failed": 0
  },
  "_seq_no": 3,
  "_primary_term": 1
}
Enter fullscreen mode Exit fullscreen mode

なお、ID の指定をしないと UUID で作成される。


ID: 1 の kaede だけ GET する

GET /customer/_doc/1
Enter fullscreen mode Exit fullscreen mode

customer インデックスの DocID 1 を GET すると

{
  "_index": "customer",
  "_id": "1",
  "_version": 1,
  "_seq_no": 0,
  "_primary_term": 1,
  "found": true,
  "_source": {
    "name": "kaede"
  }
}
Enter fullscreen mode Exit fullscreen mode

kaede が取れた。REST っぽいね。

Image description

HTTP Status もかかった時間もわかる。

これで基礎的な GET/POST は動作確認できた。



検索をする

indexName/_search
query
bool, must, match

これらを使うことで Elastic Search では検索ができる。

簡単な完全一致、完全不一致検索まで動作確認する。

index の中身を全て見る

GET /customer/_search
Enter fullscreen mode Exit fullscreen mode

indexName に _search をつけると

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "customer",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name": "kaede"
        }
      },
      {
        "_index": "customer",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "john"
        }
      },
      {
        "_index": "customer",
        "_id": "3",
        "_score": 1,
        "_source": {
          "name": "dan"
        }
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

index の中のデータが全て取れる。
これに query をつけることで、検索を実現できる。


名前で完全一致検索する

https://www.elastic.co/guide/en/welcome-to-elastic/current/getting-started-general-purpose.html#gp-gs-search-data

GET /customer/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "dan" } }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

公式ガイドを参考に query/bool/must/match で
項目: 値 で絞る。

query 事態を { } で囲わないと GET と紐付かないので注意。

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.9808291,
    "hits": [
      {
        "_index": "customer",
        "_id": "3",
        "_score": 0.9808291,
        "_source": {
          "name": "dan"
        }
      }
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode

するとしっかり名前が dan のデータが絞り込めた。
大文字小文字を区別はしない。
ID は検索するフィールドではないのでこのやり方では絞り込めない。

なお、 dan はこれ以上区切られないので、da では引っかからないが

        { "match": { "name": "良" } }
Enter fullscreen mode Exit fullscreen mode
    "hits": [
      {
        "_index": "customer",
        "_id": "zAPpVIIB6_QPx1u8MGaH",
        "_score": 0.85443234,
        "_source": {
          "name": "良太郎"
        }
      }
    ]
Enter fullscreen mode Exit fullscreen mode

良太郎 は漢字なので 良,太,郎 どれでも引っかかる。


名前で部分不一致検索する

逆に must_not を使うとそれを含まないデータを出せる

  "query": {
    "bool": {
      "must_not": [
        { "match": { "name": "dan" } }
      ]
    }
  }
Enter fullscreen mode Exit fullscreen mode

先程のを must_not に変えると

    "hits": [
      {
        "_index": "customer",
        "_id": "1",
        "_score": 0,
        "_source": {
          "name": "kaede"
        }
      },
      {
        "_index": "customer",
        "_id": "2",
        "_score": 0,
        "_source": {
          "name": "john"
        }
      }
    ]
Enter fullscreen mode Exit fullscreen mode

dan 以外が返ってくる。



まとめ

Elastic Search は Google でアカウント連携するだけで
簡単に実行環境を手に入れて勉強できる。

Mangement/Devtools にアクセスして

POST /{indexName}/_doc/{docId}
{
  "{keyName}": "{valueName}"
}
Enter fullscreen mode Exit fullscreen mode

これを打つだけでインデックス(テーブル)
と初期データが登録できる。
同じインデックスにこれを打つと追加できる。

GET /customer/_search
Enter fullscreen mode Exit fullscreen mode

これでインデックスの中身を全てみれる

GET /customer/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "dan" } }
      ]
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

こうやってクエリを渡すことで絞り込める。

dan は d や a では検索できないが
良太郎は どの文字でも検索できる。

以上。


次回

複雑な OR と AND をもつクエリも書きたい。

複数の key value を持つデータで、
所持金が 100k 以上または、職位が Manager 以上で、
クレジットカードのランクが Gold

💖 💪 🙅 🚩
kaede_io
kaede

Posted on July 29, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related