如何实现pin非空按pinOrder否则按created排序?聚合管道支持吗?
问题解答
这个排序需求完全可以通过MongoDB聚合管道实现,不需要额外在业务代码层做排序处理。
核心实现逻辑
核心是通过条件判断动态生成排序键,匹配规则:
pin字段非null的文档,按pin_order升序排序,pin_order相同时再按pin字段排序pin字段为null的文档,忽略pin_order字段,直接按created字段升序排序- 默认逻辑下
pin非空的置顶内容会排在普通内容(pin为null)前面,如果你需要调整两类内容的先后顺序,修改排序分组的权重值即可。
兼容所有MongoDB版本的通用写法
这个写法通过$addFields提前生成临时排序字段,不存在版本兼容问题:
// 替换成你的实际集合名 db.collection.aggregate([ { $addFields: { // 排序分组权重:pin非空为0(优先排列),pin为空为1(后排列) _sort_group: { $cond: { if: { $ne: ["$pin", null] }, then: 0, else: 1 } }, // 动态排序值:pin非空取pin_order,pin为空取created时间 _sort_val: { $cond: { if: { $ne: ["$pin", null] }, then: "$pin_order", else: "$created" } } } }, { $sort: { _sort_group: 1, _sort_val: 1, // 需要降序排列把1改成-1即可 pin: 1 // pin非空的内容pin_order相同时,按pin字段升序补排 } }, { // 移除临时生成的排序字段,不返回给前端 $unset: ["_sort_group", "_sort_val"] } ])
MongoDB 4.2+ 精简写法
4.2及以上版本支持在$sort阶段直接使用聚合表达式,不需要提前生成临时字段,写法更简洁:
db.collection.aggregate([ { $sort: { // 动态生成第一排序键 { $cond: { if: { $ne: ["$pin", null] }, then: "$pin_order", else: "$created" } }: 1, pin: 1 } } ])
示例数据集执行效果
针对给出的测试数据,执行上述通用管道后返回的排序结果为:
[ { "id": "62b9c1d74321afff4cb4e652", "created": "2022-06-27T14:42:31.726Z", "pin": "2022-06-27T14:42:31.703Z", "pin_order": 1 }, { "id": "629a212eda64722e286d29f6", "created": "2022-06-03T14:56:46.980Z", "pin": null, "pin_order": 1 }, { "id": "62b55d6ee0e1fa12861f8cb8", "created": "2022-06-24T06:45:02.126Z", "pin": null, "pin_order": 1 } ]
注意:如果需求不需要把pin非空的内容整体排在pin为空的内容前面,只需要去掉通用写法里的
_sort_group相关逻辑即可。
内容的提问来源于stack exchange,提问作者user10965730
相关产品推荐
相关产品推荐

