1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[Elasticsearch]mappingと異なる型でもインデキシングできる理由

Posted at

本記事でやること

Elasticsearchでは、mappingで定義した型とは異なる型のデータをインデキシングしてもエラーにならないことがあります。本記事では、以下の2点を軸にその理由を検証します。

  1. coerceパラメータがデフォルトでtrueになっており、フィールドの型にあうように変換してくれる
  2. _sourceフィールドはインデキシング時の「元のデータ」を保持・表示するためmappingの型と異なるように"見える"

実際にcoercetrue/falseのmappingを用いて異なる型のデータをインデキシングしてエラーの有無や検索結果の挙動を比較します。

対象読者

  • Elasticsearchのmappingを設計・管理している方
  • 型の厳密性やバリデーションに興味がある方

背景

mappingと異なる型のデータをインデキシングした時エラーにならなかったこと、さらに検索した時に異なる型のデータとして検索結果に表示されることがありこの挙動に疑問を感じました。

型が異なるデータをインデキシングしてもエラーにならない理由

これは、mappingのフィールドを定義する際にcoerceパラメータがデフォルトでtrueに設定されているためです。

coerceとは?

  • 異なる型の値をフィールドの型に合うように変換してくれる機能

実験

以下のようなmappingとドキュメントを使って検証を行います。

1. coerce:trueのmapping

integer型としてフィールドを定義

PUT /test-coerce-true
{
  "mappings": {
    "properties": {
      "price": {
        "type": "integer",
        "coerce": true
      }
    }
  }
}

:white_check_mark: 異なる型(文字列)の値をインサートしても成功します。

// ドキュメントの追加
POST /test-coerce-true/_doc
{
  "price": "100"
}

:white_check_mark: integer型の値で検索してもドキュメントにヒットします。

GET /test-coerce-true/_search
{
  "query": {
    "range": {
      "price": {
        "lte":200
      }
    }
  }
}
// 検索結果
{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "test-coerce-true",
        "_id": "SuLK9JcB2IXIFQK-oa7b",
        "_score": 1,
        "_source": {
          "price": "100"
        }
      }
    ]
  }
}

2. coerce:falseのmapping

PUT /test-coerce-false
{
  "mappings": {
    "properties": {
      "price": {
        "type": "integer",
        "coerce": false
      }
    }
  }
}

:x: 異なる型(文字列)の値をインサートするとエラーが発生

POST /test-coerce-false/_doc
{
  "price": "100"
}

型が異なることでdocument_parsing_exceptionが発生しています。

{
  "error": {
    "root_cause": [
      {
        "type": "document_parsing_exception",
        "reason": "[2:12] failed to parse field [price] of type [integer] in document with id 'TOLQ9JcB2IXIFQK-sq4X'. Preview of field's value: '100'"
      }
    ],
    "type": "document_parsing_exception",
    "reason": "[2:12] failed to parse field [price] of type [integer] in document with id 'TOLQ9JcB2IXIFQK-sq4X'. Preview of field's value: '100'",
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "Integer value passed as String"
    }
  },
  "status": 400
}

型が異なるように見える理由

coercetrueに設定した時、検索結果(_sourceフィールド)には文字列の値が表示されています。

GET /test-coerce-true/_search
{
  "query": {
    "range": {
      "price": {
        "lte":200
      }
    }
  }
}

coerceパラメータによって、フィールドの型に合わせて変換されたはずなのになぜ_sourceフィールドには文字列が表示されているのでしょうか。

// 検索結果
{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "test-coerce-true",
        "_id": "SuLK9JcB2IXIFQK-oa7b",
        "_score": 1,
        "_source": {
          "price": "100" // 文字列の値が表示されている
        }
      }
    ]
  }
}

:o: _sourceフィールドはインデキシング時のデータを表示しているため文字列のままになっています。Elasticsearch内部でどの型で扱われているかとは無関係です。

The _source field contains the original JSON document body that was passed at index time.

まとめ

  • Elasticsearchでは、mappingの型と異なるデータを投入してもエラーにならないことがある

  • その主な理由は、デフォルトでcoerce: trueが有効になっており、自動的に型変換が行われるから

  • 検索時に表示される_sourceは「投入したデータそのもの」であり、mappingの型とは異なることがある

  • 型の整合性を厳密に保ちたい場合は、coerce: falseを利用するのが効果的

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?