mongodb 对嵌套的对象数组进行排序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12432727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 12:49:33  来源:igfitidea点击:

Sort nested array of objects

mongodbsortingnested

提问by Kaylit

I'm looking for a way to sort a nested array of objects.

我正在寻找一种对嵌套对象数组进行排序的方法。

Here's an example:

下面是一个例子:

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

Suppose now I want to find all the name, of the answersarray, but how can I sort them in ascending order?

假设现在我要找到所有name的中,answers数组,但我怎么能排序他们升序排列?

回答by Eve Freeman

I would store it in the order you want it back out. Or sort it after you pull it out, on the client side.

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

If neither of those are possible, you can use the 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"}}}
]);

produces:

产生:

{
  "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
}

回答by corvid

This might not be helpful in this context, but I thought I'd add this. You also have the option to sort it on the write which tends to be better for denormalized collections where you don't have to sort in more than one way.

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

I found this situation in my app when creating a feed on a user.

在为用户创建提要时,我在我的应用程序中发现了这种情况。

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

I found it to be pretty handy because you can then use find()and it will be sorted by your specifications by default.

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

回答by Xavier Guihot

Starting in Mongo 4.4, the $functionaggregation operator allows applying a custom javascript function to implement behaviour not supported by the MongoDB Query Language.

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

For instance, in order to sort an array of objects by one of their fields:

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

// {
//   "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" }
//   ]
// }

This modifies the array in place, without having to apply a combination of expensive $unwind, $sortand $groupstages.

这会就地修改数组,而不必应用昂贵的$unwind,$sort$group阶段的组合。

$functiontakes 3 parameters:

$function需要3个参数:

  • body, which is the function to apply, whose parameter is the array to modify.
  • args, which contains the fields from the record that the bodyfunction takes as parameter. In our case "$answers".
  • lang, which is the language in which the bodyfunction is written. Only jsis currently available.
  • body,这是要应用的函数,其参数是要修改的数组。
  • args,其中包含该body函数作为参数的记录字段。在我们的情况下"$answers"
  • lang,这body是编写函数的语言。仅js当前可用。

回答by Philipp

After performing a find() you can use sort() on the return value.

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

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

The find would extract the name fields of all documents in the collection. The sort would then sort them by name, ascending.

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

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

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