Elasticsearch 6.8中tags数组的唯一值获取与模糊查询实现
需求1:分页获取所有唯一Tags值
由于数据量超1000万,直接用terms聚合无法高效处理分页(受限于内存和返回结果数量限制),推荐使用Composite聚合实现游标式分页,通过after参数实现skip效果,size参数控制每页返回的唯一tags数量(固定limit)。
查询DSL示例:
{ "size": 0, "aggs": { "unique_tags": { "composite": { "size": 100, // 每页返回的唯一tags数量 "sources": [ { "tag": { "terms": { "field": "tags" } } } ], "after": { "tag": "last_tag_from_previous_page" } // 上一页最后一个tag,实现跳过前面数据的效果 } } } }
说明:
- 首次查询无需
after参数,直接获取第一页数据;后续查询将上一页返回的aggregations.unique_tags.after_key作为本次的after值,即可获取下一页数据。 size设为0是为了不返回原始文档,仅返回聚合结果,节省资源开销。
需求2:Tags部分匹配搜索并分页
针对keyword类型的tags做部分匹配(如输入act返回react),可使用wildcard查询结合分页参数实现需求。若涉及深度分页(页码较大),建议用search_after替代from/size避免性能问题。
方式1:基础from/size分页(适合小页码场景)
{ "from": 0, // 跳过的文档数量,对应(页码-1)*每页数量 "size": 10, // 每页返回的文档数量 "query": { "wildcard": { "tags": "*act*" // *匹配任意字符,实现包含"act"的部分匹配 } }, "_source": ["tags"] // 仅返回tags字段,减少数据传输量 }
方式2:search_after分页(大数据量深度分页推荐)
先执行一次查询获取最后一条文档的排序字段值,后续查询通过search_after定位分页起点:
// 首次查询 { "size": 10, "query": { "wildcard": { "tags": "*act*" } }, "sort": [ { "_id": "asc" } // 选择唯一且稳定的排序字段,比如文档ID ], "_source": ["tags"] } // 后续分页查询,填入上一页最后一条文档的sort值 { "size": 10, "query": { "wildcard": { "tags": "*act*" } }, "sort": [ { "_id": "asc" } ], "search_after": ["last_document_id_from_previous_page"], "_source": ["tags"] }
说明:
- 若要进一步提升部分匹配的查询效率,可给
tags字段添加text类型的子字段并配置合适的分词器(如standard),之后使用match_phrase_prefix或query_string查询,但需要重新索引数据。基于现有keyword字段,wildcard是最直接的实现方式。
内容的提问来源于stack exchange,提问作者Suraj Dalvi
相关产品推荐
相关产品推荐

