web-dev-qa-db-ja.com

オブジェクトのネストされた配列をソートする

オブジェクトのネストされた配列をソートする方法を探しています。

次に例を示します。

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

name配列のすべてのanswersを検索したいとしますが、それらを昇順に並べ替えるにはどうすればよいですか?

18
Kaylit

私はあなたがそれを取り戻したい順序でそれを保管します。または、引き出した後でクライアント側で並べ替えます。

これらのどちらも可能でない場合は、 集約フレームワーク を使用できます。

> 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
}
30
Eve Freeman

これはこのコンテキストでは役に立たないかもしれませんが、これを追加したいと思いました。また、書き込み時に並べ替えるオプションもあります。これは、複数の方法で並べ替える必要がない非正規化コレクションに適している傾向があります。

ユーザーでフィードを作成したときに、アプリでこの状況が見つかりました。

_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()を使用できるため、かなり便利であることがわかりました。デフォルトでは、指定に従って並べ替えられます。

4
corvid

Mongo 4.4以降、 $function 集計演算子を使用すると、カスタムJavaScript関数を適用して、MongoDBクエリ言語でサポートされていない動作を実装できます。

たとえば、オブジェクトの配列をフィールドの1つで並べ替えるには、次のようにします。

// {
//   "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のみが利用可能です。
0
Xavier Guihot