Elasticsearch入門

elasticserachの最新版の7系ではtypeが使えなくなってしまいました。
にも関わらず未だにtypeありきの記事ばかりがヒットしてしまうので、触りの部分だけでもelasticserach7向けのものを用意しました。

とっちらかっていますがとりあえず現段階で公開しておきます。

公式サイト

https://www.elastic.co/guide/en/elasticsearch/reference/7.4/indices-put-mapping.html

インデックス関連

インデックスを作成

curl -XPUT 'localhost:9200/card'

「{"acknowledged":true,"shards_acknowledged":true,"index":"card"}」というようなメッセージが出たら成功です。

インデックスを確認

$ curl 'localhost:9200/_cat/indices?v'

cardというインデックスが生成されていることがわかります。

health status index                    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .kibana_task_manager_1   EMvLA0mGSz6teRxy8cdZxg   1   0          2            0     30.5kb         30.5kb
green  open   .apm-agent-configuration --tJVwgLRyC7uKjOkSyRXg   1   0          0            0       283b           283b
green  open   .kibana_1                oAsBJhsPTZaIeR5Ethtzqw   1   0          5            0     21.6kb         21.6kb
yellow open   card                     HTKwBphgSKaftEnEPpTOSw   1   1          0            0       230b           230b

インデックスの中身も確認

$ curl -X GET  'localhost:9200/card?pretty'

{
  "card" : {
    "aliases" : { },
    "mappings" : { },
    "settings" : {
      "index" : {
        "creation_date" : "1573818625817",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "HTKwBphgSKaftEnEPpTOSw",
        "version" : {
          "created" : "7040099"
        },
        "provided_name" : "card"
      }
    }
  }
}

マッピングの作成

card2というインデックスのに「title」という「keyword」タイプのフィールドを追加します。

$ curl -X PUT "localhost:9200/card2/_mapping?pretty" -H 'Content-Type: application/json' -d'
{
  "properties": {
    "title": {
      "type": "keyword"
    }
  }
}

出来上がった後のインデックスをもう一度見てみると"mappings"の中のpropatyの中にtitleがkeywordとして登録されています。

$ curl -X GET  'localhost:9200/card2?pretty'
{
  "card2" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "title" : {
          "type" : "keyword"
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "1573995034195",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "2XZ4VZZYSyWY4bJn0OLskA",
        "version" : {
          "created" : "7040099"
        },
        "provided_name" : "card2"
      }
    }
  }
}

ちなみにフィールド名を変更することで、追加としても利用できるようです。

ドキュメントを追加する

データの本体であるドキュメントを追加します。

$ curl -XPUT "localhost:9200/card2/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
    "title": "TestTitle1"
}'

結果
{
  "_index" : "card2",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

ドキュメント数が増えたか確認します。

$ curl 'localhost:9200/_cat/indices?v'
health status index                    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   card2                    2XZ4VZZYSyWY4bJn0OLskA   1   1          0            0       283b           283b
green  open   .kibana_task_manager_1   EMvLA0mGSz6teRxy8cdZxg   1   0          2            0     21.7kb         21.7kb
yellow open   caaaard                  4itFOqHbREqWz0mGkBhdNA   1   1          0            0       283b           283b
green  open   .apm-agent-configuration --tJVwgLRyC7uKjOkSyRXg   1   0          0            0       283b           283b
green  open   .kibana_1                oAsBJhsPTZaIeR5Ethtzqw   1   0          5            0     21.6kb         21.6kb
yellow open   card                     HTKwBphgSKaftEnEPpTOSw   1   1          0            0       283b           283b

ドキュメントの内容を確認する。

$ curl -X GET  'localhost:9200/card2/_doc/1?pretty'
{
  "_index" : "card2",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "title" : "TestTitle1"
  }
}

備考

mappingしていないフィールドを既存ドキュメントに対して作ってみたら、ちゃんとデータができていた。しかし指定していなかった既存フィールドがなくなってしまっていたのでデータの更新方法などはもう少し調査が必要。

ドキュメントのフィールド更新

card2インデックスのidが3のドキュメントの"title"フィールドを変更します。

curl -XPOST "localhost:9200/card2/_doc/3/_update?pretty" -H 'Content-Type: application/json' -d'
{
  "doc": { "title": "Jane Doe" }
}'

結果の確認

$ curl -XPOST "localhost:9200/card GET  'localhost:9200/card2/_doc/3?pretty'
{
  "_index" : "card2",
  "_type" : "_doc",
  "_id" : "3",
  "_version" : 6,
  "_seq_no" : 8,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "title" : "Update Title",
    "title2" : "titletitle2",
    "title4" : 33
  }
}

※調べた感じだとどうやらid被りで作成した場合も上書きになるらしい。今まではエラーだった気がするが。

追記したい内容

動的マッピング

動的マッピングについて見てみます。
elasticsearchでは上記のように_mappingでフィールドの型を静的に指定しておくことができます。
しかし、インデックスにドキュメントを追加したときにマッピングに存在していないフィールドがあった場合は、内容から自動的に型が判断されます。
これを動的マッピングと言います。

以下のようにfiled_testというインデックスを作り、定義を確認します。
作りたてなのでマッピングは存在しませんね。

$ curl -XPUT 'localhost:9200/field_test'
{"acknowledged":true,"shards_acknowledged":true,"index":"field_test"}

$ curl -X GET  'localhost:9200/field_test?pretty'
{
  "field_test" : {
    "aliases" : { },
    "mappings" : { },
    "settings" : {
      "index" : {
        "creation_date" : "1574088223080",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "pmceEarISKamfZl7KJOuFg",
        "version" : {
          "created" : "7040099"
        },
        "provided_name" : "field_test"
      }
    }
  }
}

そこに以下のようにドキュメントを作成します。

$ curl -XPUT "localhost:9200/field_test/_doc/1?pretty" -H 'Content-Type: application/json' -d'
> {
>     "title": "field_title",
>     "number": 1
> }'
{
  "_index" : "field_test",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
↑無事にドキュメントが作成されました。

ではインデックスの定義がどうなったかみてみましょう。

$ curl -X GET  'localhost:9200/field_test?pretty'
{
  "field_test" : {
    "aliases" : { },
    "mappings" : {
      "properties" : {
        "number" : {
          "type" : "long"
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        }
      }
    },
    "settings" : {
      "index" : {
        "creation_date" : "1574088223080",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "pmceEarISKamfZl7KJOuFg",
        "version" : {
          "created" : "7040099"
        },
        "provided_name" : "field_test"
      }
    }
  }
}

titleとnumberのフィールドができており、それぞれ型がtextとlongとなっていることがわかります。

ドキュメントを上書きするときにフィールドを定義しなかったらどうなるのか ドキュメントへのフィールド追加 インデックスへのフィールド追加 既存のフィールドの値変更 フィールドのタイプ変動は可能か 複数のインデックスにマッピング定義を行う。