Elasticsearch查询含指定字符串文本对应frame_number的方法
问题根因
你的代码不生效是三个明确的错误导致的:
- 接口调用错误:
get方法仅支持通过文档ID拉取单条文档,不支持传入查询条件做检索,所有条件搜索必须用search方法。 - 查询类型错误:
match查询是分词匹配查询,原生不支持*通配符语法,前后模糊匹配需要用wildcard类型查询。 - 数据结构匹配逻辑错误:ES默认会把数组类型的嵌套对象字段打平存储,直接查询
frames.text会丢失frame和text的绑定关系,哪怕匹配到文本也可能关联到错误的帧号,甚至出现跨帧匹配的脏结果。
正确实现方案
第一步:修正索引映射
要精准匹配每个帧内的文本、正确关联对应帧号,必须先把frames字段设置为nested类型,保留嵌套对象的独立关联关系,同时给文本字段加专门适配通配符查询的子字段,映射配置如下:
PUT /siv_data { "mappings": { "properties": { "platform": {"type": "keyword"}, "name_link": {"type": "keyword"}, "total_frames": {"type": "integer"}, "frames": { "type": "nested", "properties": { "frame_number": {"type": "integer"}, "text": { "type": "text", "fields": { "wildcard": {"type": "wildcard"} } } } } } } }
注意:如果你的
siv_data索引已经存在,需要先删除旧索引,按上述映射创建新索引后重新导入数据,nested类型的配置才能生效。
第二步:替换查询代码
把你原来的Python查询代码替换为如下内容,用nested查询+wildcard匹配,同时通过inner_hits返回匹配到的对应帧号:
target_str = "esstre" search_param = { "query": { "nested": { "path": "frames", "query": { "wildcard": { "frames.text.wildcard": f"*{target_str}*" } }, "inner_hits": { "_source": ["frames.frame_number"], "size": 10 } } } } # 必须调用search接口,不能用get接口 resp = _es.search(index="siv_data", body=search_param) print(resp)
结果取值说明
- 查询返回结果中,
hits.hits数组是匹配到的顶层文档,每个顶层文档下的inner_hits.frames.hits.hits数组,就是所有包含目标字符串的帧条目,其中_source.frame_number就是你需要的帧号,针对你给出的示例数据,会正确返回帧号0。 - 如果你的需求是精确匹配text数组中某一项完全等于目标字符串,不需要前后模糊匹配,可以把
wildcard查询替换为term查询,查询性能会更高。
内容的提问来源于stack exchange,提问作者Sergi Cañas
相关产品推荐
相关产品推荐

