Elastic Search按文本字段排序报错illegal_argument_exception排查
Elasticsearch按嵌套对象字段排序报错的解决方法
索引配置
为Elasticsearch的Products配置了如下索引:
{ "settings": { "index": { "number_of_shards": 3, "number_of_replicas": 0 } }, "mappings": { "properties": { "name": { "fields": { "original": { "type": "keyword" } }, "type": "text", "fielddata": true, "analyzer": "portuguese" }, "product_data": { "type": "object" } } } }
数据写入操作
通过以下请求写入数据(响应为201 created):
请求URL:http://127.0.0.1:9200/product2/_update/IMOB01
请求体:
{ "doc": { "name":"Test", "product_data": { "symbol": "IMOB01", "release_date": "2013-01-01T00:00:00" } }, "doc_as_upsert": true }
问题现象
执行搜索时,按name字段排序正常,但尝试按product_data.symbol字段排序时收到错误。
搜索请求URL:localhost:9200/product/_search
请求体:
{ "from": 0, "size": 50, "query": { "bool": { "must": { "match": { "product_data.symbol": "imob01" } } } }, "sort": [ { "product_data.symbol": {"order": "asc", "unmapped_type" : "text"}} ] }
错误响应:
{ "error": { "root_cause": [ { "type": "illegal_argument_exception", "reason": "Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [product_data.symbol] in order to load field data by uninverting the inverted index. Note that this can use significant memory." } ], "type": "search_phase_execution_exception", "reason": "all shards failed", "phase": "query", "grouped": true, "failed_shards": [ { "shard": 0, "index": "product", "node": "PfwDOAwzTZm63IHq_rt1TA", "reason": { "type": "illegal_argument_exception", "reason": "Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [product_data.symbol] in order to load field data by uninverting the inverted index. Note that this can use significant memory." } } ], "caused_by": { "type": "illegal_argument_exception", "reason": "Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [product_data.symbol] in order to load field data by uninverting the inverted index. Note that this can use significant memory.", "caused_by": { "type": "illegal_argument_exception", "reason": "Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [product_data.symbol] in order to load field data by uninverting the inverted index. Note that this can use significant memory." } } }, "status": 400 }
将product_data设为object类型是因为部分产品有不同字段,但给product_data设置fielddata:true并未解决问题。
问题原因
- 索引名称不匹配:写入数据的索引是
product2,但搜索的是product索引,这会导致搜索的索引中可能没有对应数据或映射,需先确认索引名称是否正确。 - fielddata设置位置错误:
product_data是object类型,fielddata是text字段的专属属性,给object类型设置fielddata:true不会传递到内部的product_data.symbol字段。Elasticsearch自动将product_data.symbol映射为text类型,而text字段默认不支持排序/聚合,必须针对该字段本身开启fielddata或设置keyword子字段。
解决方案
方案1:添加keyword子字段(推荐)
对于symbol这类标识性字段,使用keyword类型排序/聚合更高效,且内存占用低。需要修改索引映射并重新索引数据:
- 修改索引映射(以
product2为例):
PUT /product2/_mapping { "properties": { "product_data": { "properties": { "symbol": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } } } }
- 重新索引现有数据(确保新字段生效)
- 搜索时使用
product_data.symbol.keyword排序:
{ "from": 0, "size": 50, "query": { "bool": { "must": { "match": { "product_data.symbol": "imob01" } } } }, "sort": [ { "product_data.symbol.keyword": {"order": "asc"}} ] }
方案2:开启product_data.symbol的fielddata(不推荐)
如果不想重新索引,可以直接给product_data.symbol字段开启fielddata,但会占用较多堆内存,不建议在生产环境使用:
PUT /product2/_mapping { "properties": { "product_data": { "properties": { "symbol": { "type": "text", "fielddata": true } } } } }
之后即可使用原字段进行排序,但需监控内存使用情况。
内容的提问来源于stack exchange,提问作者Thiago Pelissari
相关产品推荐
相关产品推荐

