ビジネス的要件からソートロジックの変更に伴って、hogeという新しいフィールドでソートしたいので、以下を投げたら、掲題のエラーを食らった。
curl ":9200/foo/bar/_search?size=2&pretty" -d '{"sort":[{"hoge":"desc"}]}'
叱られている通り、hoge
というフィールドに対するmappingが無いんですって。
mappingはドキュメントがサーチエンジンに対してどのようにマップされるかを定義します。ドキュメントが検索可能なフィールドを含むときは、そのフィールドについても、どのようにトークナイズしてマップするかも定義します。Elasticsearchでは、ひとつのindexはドキュメントを独立した"mapping type"に保存します。ひとつのインデックスに対して複数の異なるmapping typeをヒモづけることも可能です。*1
なんのこっちゃ
mappingは'index/type'単位で定義されます。新しいtypeや新しいfieldを追加したとき、自動的にmappingが追加されるので、明示的に定義する必要はありません。デフォルトでつくられたmappingを上書きしたいときだけ、mappingの定義を明示しなければなりません。*2
hoge
フィールド足すと、自動的にmappingが更新される??
まずはドキュメントひとつ取得してみる
curl ":9200/foo/bar/54e5a8788bd2c75c66bc3983?pretty=true"
{ "_index" : "foo", "_type" : "bar", "_id" : "54e5a8788bd2c75c66bc3983", "_version" : 1, "found" : true, "_source":{"title":"おっぱい", "description": "This is description"} }
検索してみる
curl ":9200/foo/bar/_search?pretty=1" -d '{"query":{"match":{"description":{"query":"This"}}}}'
{ "took" : 2, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, "hits" : { "total" : 1, "max_score" : 5.4485164, "hits" : [ { "_index" : "foo", "_type" : "bar", "_id" : "54e5a8788bd2c75c66bc3983", "_score" : 5.4485164, "_source":{"title":"おっぱい", "description": "This is description"} } ] } }
mappingsの確認
curl ":9200/foo/_mappings?pretty"
{ "foo" : {// fooインデックスの "mappings" : { "bar" : {// barタイプに定義されているmappings "properties" : { "description" : { "type" : "string" }, "title" : { "type" : "string" } } } } } }
フィールドを追加してみる
curl -XPOST ":9200/foo/bar/54e5a8788bd2c75c66bc3983/_update?pretty=1" -d '{"script": "ctx._source.hoge = 100"}'
{ "_index":"foo", "_type":"bar", "_id":"54e5a8788bd2c75c66bc3983", "_version":2 }
そしてもう一回mappingsを確認
curl ":9200/foo/_mappings?pretty"
{ "foo" : {// fooインデックスの "mappings" : { "bar" : {// barタイプに定義されているmappings "properties" : { "description" : { "type" : "string" }, "hoge": { // フィールドが追加され自動的にmappingsが追加されてる! "type": "long" }, "title" : { "type" : "string" } } } } } }
追加されとるやん!
ということで、冒頭の_searchをもう一度投げてみる
curl ":9200/foo/bar/_search?size=2&pretty" -d '{"sort":[{"hoge":"desc"}]}'
{ "took" : 7, "timed_out" : false, "_shards" : { "total" : 5, "successful" : 5, "failed" : 0 }, // 以下略
成功した!
結論
- No mapping found for [hoge] in order to sort on は、index/typeのmappingsにhogeが無いことによるエラー
- 特定のフィールドのmappingsの追加は、フィールドの新規追加に伴って自動的に行われる
DRY
*1:Mapping is the process of defining how a document should be mapped to the Search Engine, including its searchable characteristics such as which fields are searchable and if/how they are tokenized. In Elasticsearch, an index may store documents of different "mapping types". Elasticsearch allows one to associate multiple mapping definitions for each mapping type.
*2:Explicit mapping is defined on an index/type level. By default, there isn’t a need to define an explicit mapping, since one is automatically created and registered when a new type or new field is introduced (with no performance overhead) and have sensible defaults. Only when the defaults need to be overridden must a mapping definition be provided.