LoginSignup
0
0

More than 3 years have passed since last update.

Elasticsearchのマッピングでintegerを指定したのに,あっれれ〜stringになってる?問題について

Last updated at Posted at 2020-03-16

はじめに

全文検索エンジンElasticsearchの勉強を始めて1ヶ月くらいの雑魚エンジニアです.まだまだ理解できていない部分が多いのが現状...(変なところあったら,コメント下さい)

今回はタイトルの通り,マッピングでintegerを指定していたのに,stringになっていて,ハマったのでその考察です.
Elasticsearchでは自動で型推論が行われるので,stirngを入れてもintにしてくれる...と思っていたのですが,検索をしたときの結果がstirngになっているときがありました.

環境

※いずれもDockerで構築
Elasticsearch 7.1.0
kibana 7.1.0

マッピングを設定

以下のコマンドは全て,kibanaのコンソール上で実行しています.(シェルからcurlコマンドを叩いてもいいのですが,入力しずらいので)

型がintegerでnumber_intというフィールドがあるマッピングを設定しておきます.

入力
PUT my_index
{
  "mappings": {
    "properties": {
      "number_int": {
        "type": "integer"
      }
    }
  }
}
結果
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "my_index"
}

スクリーンショット 2020-03-14 21.45.45.png

マッピングの確認

正しくマッピングができているか念の為,確認します.

GET my_index/_mapping
結果
{
  "my_index" : {
    "mappings" : {
      "properties" : {
        "number_int" : {
          "type" : "integer"
        }
      }
    }
  }
}

スクリーンショット 2020-03-14 21.45.01.png

(わーい,できてる〜)

stringのデータを登録してみる

マッピングではintegerとしているのですが,
「型推論が行われるから大丈夫だろ」
と思ったマヌケな僕は,stringのデータを登録してみます.

入力
PUT my_index/_doc/1
{
  "number_int": "10" 
}
結果
{
  "_index" : "my_index",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

スクリーンショット 2020-03-14 21.46.22.png

(わーい,無事登録できたよー)

が,しかし...

検索をかけてみる

number_intが20以下で検索をかけてみます.すると(結果をよく見てください)

入力
GET my_index/_search
{
  "query" : {
    "range" : {
      "number_int" : {
        "lte" : 20
      }
    }
  }
}
結果
{
  "took" : 663,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "number_int" : "10"
        }
      }
    ]
  }
}

スクリーンショット 2020-03-14 21.42.07.png

"number_int" : "10"となっています.

マッピングの型はintegerなのにあれ?
string???
なんで???
型変換してくれないの???
検索するときはinteger(20以下の20)にしているのに???

試しにintegerのデータを登録してみる

PUT my_index/_doc/1だと先ほどのドキュメントを上書きしてしまうため,2に変更しています.

入力
PUT my_index/_doc/2
{
  "number_int": 14
}
結果
{
  "_index" : "my_index",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 1
}

スクリーンショット 2020-03-14 22.25.24.png

もう一回,検索をかけてみる

もう一度,number_intが20以下で検索してみます.
すると...

入力
GET my_index/_search
{
  "query" : {
    "range" : {
      "number_int" : {
        "lte" : 20
      }
    }
  }
}
結果
{
  "took" : 550,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "number_int" : "10"
        }
      },
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "number_int" : 14
        }
      }
    ]
  }
}

スクリーンショット 2020-03-14 22.26.51.png

"_id" : "1"の方は"number_int" : "10"と先ほどと変わらずstringのままで,"_id" : "2",の方は,"number_int" : 14とintegerになっています.

もはや,わけわかめー

どうやら,_source field は,インデックス保存時に渡された値を返しているらしい

最初,Elastcisearchの公式が最も情報量が豊富なので探してみたのですが,よくわかりませんでした.

というわけで,ゴリ押しでググりまくって見つけました.

参考 : 今日のElasticsearch学び Vol.2 - Mappings編

_source fieldには実際に投入したドキュメントのそのままの値が入っている。つまりCharFilterとかTokenizerとかそういうのが全くかかっていない状態のものが入っている。詳しくは_source fieldを参照。

どうやら_source field の仕様のようです(マッピングが間違えているとばかり思っていました...).公式のリンクも貼ってくださっていたので,みてみます.

参考(公式) : _source field

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

ということから,ドキュメントとして登録されているのは型を自動で変換して,integerになっているが,
_source fieldに含まれるのは,インデックス保存時に渡された値なので,stringで返ってきたり,integerで返ってきていたみたいです.

Elasticsearchを扱うときは型に気をつけましょう〜

0
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
0
0