Elasticsearch 多值标签怎样分别过滤文档和元素?
先确定结果是整篇文档还是单个标签。包含目标标签的文档可用 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。
推荐专题
热门阅读
-
-
下载
- |
-
-
下载
- 《行尸走肉第一章》免安装中文汉化硬盘版下载
- 单机|436 MB
- 一款以动作冒险为主题的游戏
-
-
下载
- 《街头霸王X铁拳》免安装中文汉化硬盘版下载
- 单机|111MB
- 一款非常好玩的格斗游戏
-
-
下载
- |
-
-
下载
- 《暗黑破坏神3》免安装繁体中文正式版下载
- 单机|7630 MB
- 一款以角色扮演为主题的游戏
-
-
下载
- 《马克思佩恩3》免安装硬盘版下载
- 单机|27033 MB
- 一款以第三人称射击为主题的游戏