1

解決済みの $match の使用に関するトピックを作成しましたが、今はより複雑な例で立ち往生しています。たとえば、私の Json の構造体を考えてみます。

{
    user: 'bruno',
    answers: [
        {id: 0, value: 3.5},
        {id: 1, value: "hello"}
    ]
}

'value' に含まれる値に、0 に等しい識別子 'id' のみを追加または並べ替え、いくつかの変換を適用したいと思います (たとえば、並べ替えメソッドなど)。

次のデータを検討してください。

db.my_collection.insert({ user: 'bruno', answers: [ {id: 0, value: 3.5}, {id: 1, value: "hello"}]})

db.my_collection.insert({ user: 'bruno2', answers: [ {id: 0, value: 0.5}, {id: 1, value: "world"}]})

私は使用してみました:

db.my_collection.aggregate ({$sort: {"answers": {"$elemMatch": {id: 0, value: -1}}}})

しかし、うまくいきませんでした。予想される結果: {user: 'bruno2' 回答: [{id: 0, value: 0.5}, {id: 1, value: "world"}]}, {user: 'bruno' 回答: [{id: 0、値: 3.5}、{id: 1、値: "こんにちは"}]})

ありがとうございました。

4

1 に答える 1

7

まず、並べ替えの例の形式が正しくないことに注意してください。集計メソッドは配列を入力として受け取り、配列の各要素が集計パイプラインのステージを指定します。また、$elemMatch演算子は $sort ステージの一部として使用できないことに注意してください。

並べ替えの例でやろうとしていることを達成する 1 つの方法は、集計フレームワークの$unwindパイプライン演算子を使用することです。配列を巻き戻すと、配列要素が 1 つずつ別々のドキュメントに剥がれます。たとえば、次のクエリ

db.my_collection.aggregate([ {$unwind: "$answers"} ]);

次のようなものを返します。

[
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 0,
            "value" : 3.5
        }
    },
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 1,
            "value" : "hello"
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 0,
            "value" : 0.5
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 1,
            "value" : "world"
        }
    }
]

$match フェーズを追加すると、answers.id がゼロのドキュメントのみを取得できます。最後に、$sort フェーズを使用すると、answers.value で並べ替えることができます。全体として、集計クエリは次のとおりです。

db.my_collection.aggregate([
    {$unwind: "$answers"},
    {$match: {"answers.id": 0}},
    {$sort: {"answers.value": -1}}
]);

そして出力:

[
    {
        "_id" : ObjectId("5237157f3fac8e36fdb0b96e"),
        "user" : "bruno",
        "answers" : {
            "id" : 0,
            "value" : 3.5
        }
    },
    {
        "_id" : ObjectId("523715813fac8e36fdb0b96f"),
        "user" : "bruno2",
        "answers" : {
            "id" : 0,
            "value" : 0.5
        }
    }
]

あなたの質問に基づいて、常に $unwind や集計フレームワークが必要になるとは思えません。代わりに、answers.id が 0 で、answers.value が 3.5 のドキュメントを検索し、answers.value を 4 に変更する場合は、find を $elemMatch に続けて db.collection.save() を使用できます。

doc = db.my_collection.findOne({"answers": {$elemMatch: {"id": 0, "value": 3.5}}});
for (i=0; i<doc.answers.length; i++) {
  if (doc.answers[i].id === 0) {
    doc.answers[i].value = 4;
    db.my_collection.save(doc);
    break;
  }
}
于 2013-09-16T16:13:17.630 に答える