MongoDB - 如何查找数组字段

时间:2017-05-24 08:09:04

标签: mongodb aggregation-framework

我有一个包含名为'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',
  ...
}]

2 个答案:

答案 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;因为这是nullDate进行排序的方式。

如果您想更新文档,以便只需选择要使用常规查找进行排序的属性,那么您可以执行此更新:

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);