Elasticsearch如何基于子项字段限制数组子项搜索?
解决Elasticsearch数组对象的同项条件查询问题
问题原因
你当前的查询返回不符合预期的文档,是因为Elasticsearch默认会将数组中的对象扁平化存储。也就是说,partes.IdTipoParticipacao和partes.Nome会被处理成两个独立的多值字段,而非关联的对象属性。这就导致partes.IdTipoParticipacao:78和partes.Nome:"Benício Lucca Caleb Alves"可以匹配文档中不同数组项的内容——只要文档里存在任意一个项满足IdTipoParticipacao=78,同时存在任意一个项满足Nome匹配,就会返回该文档。
解决方案
要实现“同一个数组项同时满足多个条件”的查询,必须将partes字段设置为**nested类型**,然后使用nested查询来关联同一项内的多个条件。
1. 配置正确的索引Mapping
首先需要确认你的索引中partes字段的类型是nested。如果之前未设置,需重新创建索引并配置Mapping:
PUT indicedocs { "mappings": { "properties": { "Id": {"type": "keyword"}, "NivelSigilo": {"type": "integer"}, "Numero": {"type": "keyword"}, "IdAreaAtuacao": {"type": "integer"}, "NumeroFormatado": {"type": "keyword"}, "partes": { "type": "nested", // 核心:将数组字段设为nested类型 "properties": { "IdTipoParticipacao": {"type": "integer"}, "TipoParte": {"type": "integer"}, "Participacao": {"type": "text"}, "Policial": {"type": "text"}, "CPF": {"type": "keyword"}, "CPFFormatado": {"type": "keyword"}, "Nome": {"type": "text"}, "Nacionalidade": {"type": "text"}, "CNPJ": {"type": "keyword"}, "CNPJFormatado": {"type": "keyword"} } } } } }
配置完成后,重新导入你的文档数据。
2. 编写符合要求的查询
使用nested查询包裹针对partes数组项的条件,确保同一项内同时满足IdTipoParticipacao=78和Nome匹配,同时排除根文档IdAreaAtuacao为44、1的情况:
GET indicedocs/_search { "size": 1001, "query": { "bool": { "must": [ { "nested": { // 用nested查询关联数组项内的多个条件 "path": "partes", "query": { "bool": { "must": [ { "term": { "partes.IdTipoParticipacao": 78 } }, { "query_string": { "query": "\"Emilly e Diogo Financeira Ltda\"", "fields": ["partes.Nome"] } } ] } } } } ], "must_not": [ { "terms": { "IdAreaAtuacao": [44, 1] } } ] } } }
该查询只会返回以下文档:
- 根文档的
IdAreaAtuacao不是44或1; - 存在至少一个
partes数组项,同时满足IdTipoParticipacao=78且Nome匹配目标文本。
如果需要只返回匹配的数组项(而非整个文档),可在nested查询中添加inner_hits参数:
GET indicedocs/_search { "size": 1001, "query": { "bool": { "must": [ { "nested": { "path": "partes", "query": { "bool": { "must": [ {"term": {"partes.IdTipoParticipacao": 78}}, {"query_string": {"query": "\"Emilly e Diogo Financeira Ltda\"", "fields": ["partes.Nome"]}} ] } }, "inner_hits": {} // 返回匹配的数组项详情 } } ], "must_not": [{"terms": {"IdAreaAtuacao": [44, 1]}}] } } }
内容的提问来源于stack exchange,提问作者Carlos Barros
相关产品推荐
相关产品推荐

