MongoDB Atlas Search管道中如何对任意字段实现高效排序
性能下降原因
你当前使用的是聚合管道独立的$sort阶段,该阶段需要先拉取$search返回的所有匹配文档到MongoDB查询层做全量内存排序,哪怕最终只返回10条结果,也需要处理所有符合搜索条件的文档,数据量大的时候自然会出现性能暴跌。你为ei0创建的普通B树索引无法在Atlas Search的查询链路中生效,因为$search走的是独立的Lucene Search索引体系,两类索引不互通。
优化方案
直接在$search阶段内部配置排序规则,利用Search索引内置的排序能力,Lucene可以直接基于你已经提前加入Search索引的字段完成排序,直接返回指定数量的结果,不需要全量处理匹配文档,性能和无排序的$search查询几乎一致。
修改后的查询示例
db.collection.aggregate([{ $search: { "index": "test_index1", "compound": { "filter": [{ "equals": { "path": "listId", "value": ObjectId("613098df46239505942b8b13") } }], "must": [{ "text": { "query": "Los Angeles", "path": { "wildcard": "*" } } }] }, // 内置排序配置,写法和独立$sort完全一致 "sort": { "ei0": -1 }, // 直接在$search阶段限制返回条数,进一步减少传输开销 "limit": 10 } }]);
注意事项
- 所有用于排序的字段必须提前加入Search索引,且类型和字段实际存储类型一致:数字字段需配置为
number类型,日期字段需配置为date类型,字符串字段如果要排序需要配置为keyword类型而非text类型,否则排序结果会不符合预期。 - 支持多字段混合排序,写法和普通
$sort完全一致,比如同时按ei0降序、ed1升序排序可以写成"sort": {"ei0": -1, "ed1": 1}。 - 如果需要同时按搜索匹配度和业务字段排序,可以把
searchScore(搜索相关性得分)加入排序规则,比如"sort": {"searchScore": -1, "ei0": -1}即可实现先按匹配度从高到低,再按ei0从大到小排序。
内容的提问来源于stack exchange,提问作者Jimmie Andersson
相关产品推荐
相关产品推荐

