我有这个数据,我想按两个字段排序:首先是具体地址(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'}}}
]);