ElasticSearch如何实现MyFirstMappingType全部字段匹配且不跨实例混配
问题描述
需要编写Elasticsearch查询语句,要求匹配MyFirstMappingType类型对象的所有属性:只要同一个对象内有一个属性不匹配就不返回对应条目,不允许跨不同MyFirstMappingType实例混合匹配字段值。
原有映射配置
"mappings": { "item": { "_all": { "enabled": "false" }, "properties": { "MyFirstMappingType": { "properties": { "field1": { "type": "keyword" }, "field2": { "type": "keyword" }, "field3": { "type": "text", "index": "false" } } } } } }
原有查询存在的问题
当前编写的查询只能实现各字段分别匹配,当条目包含多个MyFirstMappingType实例时会出现跨实例混配的问题,例如以下查询会错误返回不符合要求的条目:
GET myfirst/item/_search { "from": 0, "size": 38, "_source": [ "MyFirstMappingType" ], "query": { "bool": { "filter": [ { "term": { "field1": "foo" } }, { "term": { "field2": "bar" } }, { "term": { "field3": "world" } } ] } } }
错误匹配示例条目
以下条目不存在任何一个同时满足field1=foo、field2=bar、field3=world的MyFirstMappingType实例,但会被上述查询错误命中:
"MyFirstMappingType" : [ { "field1" : "foo", "field2" : "bar", "field3" : "hello" }, { "field1" : "foo", "field2" : "world", "field3" : "foo" }, { "field1" : "foo", "field2" : "foo", "field3" : "world" } ]
解决方案
第一步:调整映射配置
问题根源是普通对象数组在Elasticsearch中会被打平索引,所有同名字段会合并为一个数组,丢失对象所属关联关系。需要做两处调整:
- 将
MyFirstMappingType的类型设置为nested,保留数组内每个对象的独立关联关系 - 原有配置中
field3的index属性为false,无法被查询,需要改为true
调整后的映射如下:
"mappings": { "item": { "_all": { "enabled": "false" }, "properties": { "MyFirstMappingType": { "type": "nested", "properties": { "field1": { "type": "keyword" }, "field2": { "type": "keyword" }, "field3": { "type": "text", "index": "true" } } } } } }
注意:修改映射后需要重建索引重新写入数据才能生效。
第二步:使用Nested查询
查询时使用nested语法指定查询路径,所有匹配条件都限定在同一个MyFirstMappingType实例内:
GET myfirst/item/_search { "from": 0, "size": 38, "_source": [ "MyFirstMappingType" ], "query": { "nested": { "path": "MyFirstMappingType", "query": { "bool": { "filter": [ { "term": { "MyFirstMappingType.field1": "foo" } }, { "term": { "MyFirstMappingType.field2": "bar" } }, { "match": { "MyFirstMappingType.field3": "world" } } ] } } } } }
注意:nested查询的字段路径需要写全路径
MyFirstMappingType.xxx,且field3为text类型,需要用match而非term查询。
内容的提问来源于stack exchange,提问作者Caleb
相关产品推荐
相关产品推荐

