【初心者向け】Elasticsearchのマッピング(mapping)を触ってみる

最終更新日: 5月 11, 2023

マッピングとは以下のように説明されています。

Mapping is the process of defining how a document, and the fields it contains, are stored and indexed.

ElasticsearchのindexにJSONをドキュメントとして登録する際に、このフィールドは日付である、このフィールドはテキストである、といったフィールドの型付けを行うための情報です。フィールドの型付けはどのように検索を行うかに応じて決定します。RDBでいうところのcreate table文に近いです。ただし、RDBと異なりElasticsearchでは特に定義を行わなくともデータの登録が可能で、自動でマッピングされます。(動的マッピングと表現されています。)

マッピングのイメージ

対象のデータには3つのフィールドが必ずあるが、ほかのフィールドはあったりなかったり、また今後一部のデータが新しいフィールドを持つようになる、といった場合にも3つのフィールドには静的マッピングを行い、ほかを動的マッピングによってマッピング定義の変更なくデータの登録が可能です。

本記事ではこのマッピングで定義できる(よく使いそうな)フィールドのデータ型について触っていきます。ローカルにElasticsearchを立てる方法はこちら。動的マッピングについては割愛します。

キーワード\keyword型

以下でマッピングを定義することでデータがkeyword型となります。

//マッピング定義
put demo-index
{
  "mappings":{
    "properties":{
      "testField":{
        "type": "keyword"
      }
    }
  }
}
//データ登録
put demo-index/_doc/1
{
  "testField":"aaa"
}
//データ取得
get demo-index/_doc/1
//結果
  "_source": {
    "testField": "aaa"
  }

複数のデータを格納することもできます。

//データ登録
put demo-index/_doc/1
{
  "testField":["bbb","aaa","ccc","aaa","ccc"]
}
//データ取得の結果
  "_source": {
    "testField": [
      "bbb",
      "aaa",
      "ccc",
      "aaa",
      "ccc"
    ]
  }

keyword型に指定できるオプションに触っていきます。

■doc_values

put demo-index
{
  "mappings":{
    "properties":{
      "testField":{
        "type": "keyword",
        "doc_values": false
      }
    }
  }
}

ドキュメントを登録する際、より最適な検索を行うためにインデックスが作成されます。これがあるために、特定のフィールドをもつドキュメントの検索が早くなります。一方でソートや集計等を行う場合は、このインデックスによるドキュメント検索ではなく、別に専用のデータ構造が生成されるとのことです。ソートや集計に特化したデータ形式を作成しているというわけですね。doc_valuesにfalseを指定することで、このソートや集計に特化したデータ構造の生成を抑制できるようです。

keyword型として扱いたいが、ソートや集計が不要な場合には、ディスク領域の確保を優先してdoc_valuesをfalseにすることがあるかもしれません。

■index

put demo-index
{
  "mappings":{
    "properties":{
      "testField":{
        "type": "keyword",
        "index": false
      }
    }
  }
}

doc_valuesでも説明した、ドキュメント登録時に生成される検索のための転置インデックスの生成オプションです。indexにfalseを指定することで、転置インデックスを生成しないためディスク領域を優先することが出来ます。

indesとdoc_valuesをfalseにしたときのstore.sizeは以下の通りでした。各インデックスには同じデータを同じ件数投入しています。

指定なしdoc_values:falseindex:falsedoc_values,index:false
267kb217.9kb168.2kb179.8kb

データ量がそこまで大きくないので誤差の範囲だと思いますが、index:falseが一番小さくなりました。(データ登録後、一通りrefreshcache clearflushforcemergeをやったうえで確認しました。)

■store

put demo-index
{
  "mappings":{
    "properties":{
      "testField":{
        "type": "keyword",
        "store": true
      }
    }
  }
}

store:trueを指定したフィールドはフィールド単位で保存されます。通常はドキュメント検索すると”_source”フィールドにデータが保存されていますが、データの一部に巨大な文字列が入っている場合に、その文字列を取得せず、必要なフィールドのみ取得したい場合に選択肢に入るオプションのようです。

■ignore_above

put demo-index
{
  "mappings":{
    "properties":{
      "testField":{
        "type": "keyword",
        "ignore_above": 10
      }
    }
  }
}

指定された数値以上の値をもつデータはインデックス付けされなくなります。

//登録
post demo-index/_doc/?pretty=true&refresh=true
{
  "testField":["12345678901234","asdfg"]
}

//検索1 ヒットする
get demo-index/_search
{
  "query":{
    "wildcard": {
      "testField": "abc*"
    }
  }
}
//検索2 ヒットしない
get demo-index/_search
{
  "query":{
    "wildcard": {
      "testField": "123*"
    }
  }
}

■fields

put demo-index
{
  "mappings":{
    "properties":{
      "testField":{
        "type": "keyword",
        "fields": {
          "text": {
            "type": "text"
          }
        }
      }
    }
  }
}

フィールドに追加のデータフィールドを定義できます。上記はkeywordフィールドとtextフィールドを同じ項目に充てています。

// 検索 ヒットする(keyword型)
get demo-index/_search
{
  "query":{
    "term": {
      "testField": {
        "value": "data"
      }
    }
  }
}

// 検索 ヒットする(text型)
get demo-index/_search
{
  "query":{
    "term": {
      "testField.text": {
        "value": "data"
      }
    }
  }
}