我有一个包含名为'servicePlans'数组的项目的集合,每个servicePlan都有一个日期。我想对具有id = x的servicePlan的日期进行排序。
例如:
[{
_id: '1',
servicePlans: [{
_id: 'x1',
date: '2017-01-02'
},{
_id: 'x2',
date: '2017-01-01'
}]
},{
_id: '2',
servicePlans: [{
_id: 'x1',
date: '2017-01-01'
},{
_id: 'x2',
date: '2017-01-02'
}]
}]
当使用id:'x1'对servicePlan进行排序时,结果为:
[{
_id: '2',
...
},{
_id: '1',
...
}]
答案 0 :(得分:1)
你可以通过一些聚合
来做到这一点db.test.aggregate([
{ "$unwind" : "$servicePlans" },
{ "$match" : { "servicePlans._id" : "x1" } },
{ "$sort" : { "servicePlans.date" : 1 } }
]);
这将得到以下结果:
{ "_id" : "2", "servicePlans" : { "_id" : "x1", "date" : "2017-01-01" } }
{ "_id" : "1", "servicePlans" : { "_id" : "x1", "date" : "2017-01-02" } }
答案 1 :(得分:1)
通过聚合动态地做到这一点,聚合可以计算要排序的字段,那么这将是最有效的方式:
var match = "x1";
db.collection.aggregate([
{ "$project": {
"servicePlans": 1,
"order": {
"$arrayElemAt": [
{ "$filter": {
"input": "$servicePlans",
"as": "sp",
"cond": { "$eq": [ "$$sp._id", match ] }
}},
0
]
}
}},
{ "$sort": { "order": -1 } }
])
这会返回所有内容,返回null
后无法匹配的任何内容,然后按照降序排列'或者在升序之前#39;因为这是null
与Date
进行排序的方式。
如果您想更新文档,以便只需选择要使用常规查找进行排序的属性,那么您可以执行此更新:
let ops = [];
db.collection.find().forEach(doc => {
let update = {};
doc.servicePlans.forEach(plan => {
update["servicePlan_" + plan._id] = plan.date;
})
ops = [
...ops,
{
"updateOne: {
"filter": { "_id": doc._id },
"update": { "$set": update }
}
}
];
if ( ops.length >= 500 ) {
db.collection.bulkWrite(ops);
ops = [];
}
})
if ( ops.length > 0 )
db.collection.bulkWrite(ops);