MongoDB:对嵌套的对象数组进行排序

时间:2012-09-14 22:22:24

标签: mongodb sorting nested

我正在寻找一种对嵌套的对象数组进行排序的方法。这是一个例子:

answers: [
           {name: 'paul', state: 'RU'},
           {name: 'steve', state: 'US'}, 
           {name: 'mike', state: 'DE'}, 
           ...
         ]

现在假设我想查找name数组的所有answers,但是按升序排序,我该如何实现呢?

4 个答案:

答案 0 :(得分:25)

我会按照您想要的顺序存储它。或者在客户端将其拉出后对其进行排序。

如果这些都不可能,您可以使用aggregation framework

> db.test.insert({answers: [
...                 {name: 'paul', state: 'RU'},
...                 {name: 'steve', state: 'US'}, 
...                 {name: 'mike', state: 'DE'}]});
> db.test.insert({answers: [
...                 {name: 'paul', state: 'RU'},
...                 {name: 'steve', state: 'US'}, 
...                 {name: 'xavier', state: 'TX'}]});

db.test.aggregate([
  {$unwind: "$answers"}, 
  {$sort: {"answers.name":1}}, 
  {$group: {_id:"$_id", answers: {$push:"$answers"}}}
]);

产生

{
  "result" : [
  {
    "_id" : ObjectId("5053b2477d820880c3469364"),
    "answers" : [
      {
        "name" : "paul",
        "state" : "RU"
      },
      {
        "name" : "steve",
        "state" : "US"
      },
      {
        "name" : "xavier",
        "state" : "TX"
      }
    ]
  },
  {
    "_id" : ObjectId("5053af9f7d820880c3469363"),
    "answers" : [
      {
        "name" : "mike",
        "state" : "DE"
      },
      {
        "name" : "paul",
        "state" : "RU"
      },
      {
        "name" : "steve",
        "state" : "US"
      }
    ]
  }
],
  "ok" : 1
}

答案 1 :(得分:4)

这可能在这方面没有帮助,但我想我会添加这个。您还可以选择在写入时对其进行排序,这对于非常规化集合而言往往更好,您不必以多种方式进行排序。

我在为用户创建Feed时在我的应用中发现了这种情况。

Meteor.users.helpers({
  'addToFeed': function (gameId, pushData) {
    check(pushData, FeedSchema);
    Meteor.users.update({
      _id: this._id,
      "games.gameId": gameId
    }, {
      $push: {
        "games.$.feed": {
          $each: [pushData],
          $sort: { timestamp: -1 }
        }
      }
    });
  }
});

我发现它非常方便,因为您可以使用find(),默认情况下会按照您的规格进行排序。

答案 2 :(得分:1)

Mongo 4.4开始,$function聚合运算符允许应用自定义javascript函数来实现MongoDB查询语言不支持的行为。

例如,为了按照对象的字段之一对数组进行排序:

// {
//   "answers" : [
//     { "name" : "steve",  "state" : "US" },
//     { "name" : "xavier", "state" : "FR" },
//     { "name" : "paul",   "state" : "RU" }
//   ]
// }
db.collection.aggregate(
  { $set:
    { "answers":
      { $function: {
          body: function(answers) { return answers.sort((a, b) => a.name > b.name); },
          args: ["$answers"],
          lang: "js"
      }}
    }
  }
)
// {
//   "answers" : [
//     { "name" : "paul",   "state" : "RU" },
//     { "name" : "steve",  "state" : "US" },
//     { "name" : "xavier", "state" : "FR" }
//   ]
// }

这将修改数组的位置,而不必应用昂贵的$unwind$sort$group阶段的组合。

$function具有3个参数:

  • body,这是要应用的函数,其参数是要修改的数组。
  • args,其中包含body函数作为参数的记录中的字段。在我们的情况下,"$answers"
  • lang,这是编写body函数的语言。当前仅js可用。

答案 3 :(得分:-3)

执行find()后,您可以对返回值使用sort()。

db.collection.find({},{"answers.name":1}).sort({"answers.name":1})

find将提取集合中所有文档的名称字段。然后排序将按名称对其进行排序,升序。

http://www.mongodb.org/display/DOCS/Sorting+and+Natural+Order