如何在MongoDB上"sort"嵌套的对象数组,因此所有具有特定值的项目都是第一个?



我有这个数据,我想按两个字段排序:首先是具体地址(details.address),例如"Tel Aviv"。其次是按常规排序,按细节排序。成本字段。以下是我的数据:

[{
"_id": "123",
"details": [{
"_id": "1",
"address": "Ramat Gan",
"cost": "50"
}, {
"_id": "2",
"address": "Tel Aviv",
"cost": "30"
}]
},
{
"_id": "456",
"details": [{
"_id": "4",
"address": "Modi'in",
"cost": "40"
}, {
"_id": "5",
"address": "Tel Aviv",
"cost": "20"
}]
}
]

,我想在两次排序后得到这个数据:

[{
"_id": "456",
"details": [{
"_id": "5",
"address": "Tel Aviv",
"cost": "20"
}, {
"_id": "4",
"address": "Modi'in",
"cost": "40"
}, {
"_id": "123",
"details": [{
"_id": "2",
"address": "Tel Aviv",
"cost": "30"
}, {
"_id": "1",
"address": "Ramat Gan",
"cost": "50"
}]
}]
}]

实际上,我想按我的特定值地址(在本例中是'Tel Aviv')进行排序

如果您希望按成本进行拆分和排序,您可以扩展@BuzzMoschetti的解决方案$group部分以使用$cond:

db.collection.aggregate([
{$unwind: "$details"},
{$sort: {"details.cost": 1}},
{
$group: {
_id: "$_id",
top: {
$push: {
$cond: [{$eq: ["$details.address", "Tel Aviv"]}, "$details", "$$REMOVE"]
}
},
bottom: {
$push: {
$cond: [{$ne: ["$details.address", "Tel Aviv"]}, "$details", "$$REMOVE"]
}
}
}
},
{$project: {details: {$concatArrays: ["$top", "$bottom"]}}}
])

看看它在操场的例子中是如何工作的

如果您只想先按特定地址订购:

db.collection.aggregate([
{
$project: {
top: {
$filter: {
input: "$details",
as: "item",
cond: {$eq: ["$$item.address", "Tel Aviv"]}
}
},
bottom: {
$filter: {
input: "$details",
as: "item",
cond: {$ne: ["$$item.address", "Tel Aviv"]}
}
}
}
},
{
$project: {
details: {$concatArrays: ["$top", "$bottom"]}
}
}
])

查看它在playground示例中的工作原理top-city

非常简单:$unwind然后re-$group。当跨文档边界排序数组时,你几乎别无选择,只能使用$unwind来让$sort正常工作。

db.foo.aggregate([
{$unwind: '$details'}
,{$sort: {'details.address':-1,'details.cost':1}}
// Rebuild the original doc; $push will *preserve* the sorted
// order of address+cost following from the stage above:
,{$group: {_id:'$_id', details: {$push: '$details'}}}
]);

相关内容

  • 没有找到相关文章