shnagaiの日記

主にエンジニアリング関連のトピックについて雑多に書いています

Elasticsearchで既にあるインデックスのスキーマを変更する方法

プロダクション環境でElasticsearch+kibana(fluentd)でログ可視化運用をしてみてわかった事でElasticsearchのマッピングについて記事を書いたところ、下記のようなツッコミをいただいたので実際に試してみた。

内容は、新しいフィールドが追加される時に、事前にスキーマ定義しないと型がStiringのanalyze(分かち書きあり)にされるので、事前にテンプレート作りましょという内容を書いたのですが、既存のインデックスについてもフィールドのスキーマ変更出来るという事でした。

今回の例では、[c-ip]というフィールドがdynamic_templatesでnot_analyzedが定義されていますが、このフィールドにmulti_fieldを使ってanalyze(分かち書きあり)のドキュメントも追加してみたいと思います。

まずは既存のスキーマ確認

$ curl -XGET 127.0.0.1:9200/testindex/rs/_mapping?pretty
{
  "rs" : {
    "dynamic_templates" : [ {
      "string_template" : {
        "mapping" : {
          "index" : "not_analyzed",
          "type" : "string"
        },
        "match" : "*",
        "match_mapping_type" : "string"
      }
    } ],
    "_source" : {
      "compress" : true
    },
    "properties" : {
      "@log_name" : {
        "type" : "string",
        "index" : "not_analyzed",
        "omit_norms" : true,
        "index_options" : "docs"
      },
      "@timestamp" : {
        "type" : "date",
        "format" : "dateOptionalTime"
      },
      "c-ip" : {
        "type" : "string",
        "index" : "not_analyzed",
        "omit_norms" : true,
        "index_options" : "docs"
      }
    }
  }
}

マッピング更新APIを使って、c-ipフィールドをmulti_fieldにスキーマ変更

ana.c-ipで分かち書きされたドキュメントを検索出来るようにする

curl -XPUT  127.0.0.1:9200/testindex/_mapping/rs -d '
{
  "properties" : {
    "c-ip" : {"type":"multi_field",
      "fields":{
        "c-ip":{"type":"string","index":"analyzed"},
        "full":{"type":"string","index":"not_analyzed"}
      }
    }
  }
}'

変更後のスキーマ確認

変更後のスキーマを確認すると[c-ip]がmulti_fieldに変わっています。

#この変更は、次から投入されるドキュメントに対して有効になりますが、すでにインデックス上にあるドキュメントは変わらないので要注意です。
$ curl -XGET 127.0.0.1:9200/testindex/rs/_mapping?pretty
{
  "rs" : {
    "dynamic_templates" : [ {
      "string_template" : {
        "mapping" : {
          "index" : "not_analyzed",
          "type" : "string"
        },
        "match" : "*",
        "match_mapping_type" : "string"
      }
    } ],
    "_source" : {
      "compress" : true
    },
    "properties" : {
      "@log_name" : {
        "type" : "string",
        "index" : "not_analyzed",
        "omit_norms" : true,
        "index_options" : "docs"
      },
      "@timestamp" : {
        "type" : "date",
        "format" : "dateOptionalTime"
      },
      "c-ip" : {
        "type" : "multi_field",
        "fields" : {
          "ana" : {
            "type" : "string"
          },
          "c-ip" : {
            "type" : "string",
            "index" : "not_analyzed",
            "omit_norms" : true,
            "index_options" : "docs",
            "include_in_all" : false
          }
        }
      }
    }
  }
}

簡単ですが、@johtaniありがとうございました。