详情

首页手游攻略 Elasticsearch 多值标签怎样分别过滤文档和元素?

Elasticsearch 多值标签怎样分别过滤文档和元素?

佚名 2026-11-06 09:10:01

先确定结果是整篇文档还是单个标签。包含目标标签的文档可用 term,单个元素则在 ES|QL 展开后筛选。

1. 先用 term 查包含目标值的文档

在 Elasticsearch 9.2.0 测试节点的 Kibana Dev Tools Console 执行以下代码。tags 用 keyword 保存。数据包括混合标签、单标签和空数组。

PUT demo-mv-filter
{"mappings": {"properties": {"event_id": {"type": "integer"}, "tags": {"type": "keyword"}}}}

PUT demo-mv-filter/_doc/1?refresh=true
{"event_id": 1, "tags": ["blue", "red"]}

PUT demo-mv-filter/_doc/2?refresh=true
{"event_id": 2, "tags": ["blue"]}

PUT demo-mv-filter/_doc/3?refresh=true
{"event_id": 3, "tags": ["red"]}

PUT demo-mv-filter/_doc/4?refresh=true
{"event_id": 4, "tags": []}
POST demo-mv-filter/_search
{"query": {"bool": {"filter": [{"term": {"tags": "red"}}]}}, "sort": ["event_id"]}
# 命中文档 1、3,文档 1 的 _source.tags 仍是 ["blue","red"]

term 匹配到任一已索引的精确值时,整个文档通过。bool.filter 把这个条件放进过滤上下文。文档 4 的空数组没有可匹配值。

2. 展开后按元素筛选

ES|QL 的普通等值比较需要单值。本例把比较放在展开前时,文档 1 的两个值不会通过比较,只有文档 3 保留。

POST /_query
{"query": "FROM demo-mv-filter | WHERE tags == "red" | KEEP event_id, tags | SORT event_id"}
# values: [[3,"red"]]

MV_EXPAND 将文档 1 拆为 blue 和 red 两行,随后 WHERE 只保留 red。排序放在展开与过滤之后。

POST /_query
{"query": "FROM demo-mv-filter | MV_EXPAND tags | WHERE tags == "red" | KEEP event_id, tags | SORT event_id"}
# values: [[1,"red"],[3,"red"]]

3. 在读取阶段先筛文档,展开后保留元素条件

用 ES|QL 请求体的 filter 提前淘汰不含 red 的文档,再用原 WHERE 从剩余文档中筛出 red 行。这里的下推指显式使用源文档过滤。

POST /_query
{"query": "FROM demo-mv-filter | MV_EXPAND tags | WHERE tags == "red" | KEEP event_id, tags | SORT event_id", "filter": {"term": {"tags": "red"}}}
# values: [[1,"red"],[3,"red"]]

文档 1 通过早期过滤后仍含 blue。如果移除展开后的 WHERE,blue 也会输出。提前过滤的条件必须对目标元素行成立,遇到缺失值、否定或复杂组合时先验证结果等价。这里验证了四个文档的返回值,实际性能收益需用自己的数据和执行信息确认。

只取包含标签的文档时用 term。要逐元素分析时先展开,再保留元素条件。索引级条件能安全缩小候选文档时,可同时放进请求 filter。

点击查看更多
推荐专题
热门阅读