sql >> データベース >  >> NoSQL >> MongoDB

異なるフィールドでグループ化する方法

    それ 大変でした!

    まず、必要な解決策:

    db.test.aggregate([
     { "$match": { "user": "Hans" } },
     // duplicate each document: one for "age", the other for "childs"
     { $project: { age: "$age", childs: "$childs",
                   data: {$literal: ["age", "childs"]}}},
     { $unwind: "$data" },
     // pivot data to something like { data: "age", value: "40" }
     { $project: { data: "$data",
                   value: {$cond: [{$eq: ["$data", "age"]},
                                   "$age", 
                                   "$childs"]} }},
     // Group by data type, and count
     { $group: { _id: {data: "$data", value: "$value" }, 
                 count: { $sum: 1 }, 
                 value: {$first: "$value"} }},
     // aggregate values in an array for each independant (type,value) pair
     { $group: { _id: "$_id.data", values: { $push: { count: "$count", value: "$value" }} }} ,
     // project value to the correctly name field
     { $project: { result: {$cond: [{$eq: ["$_id", "age"]},
                                   {age: "$values" }, 
                                   {childs: "$values"}]} }},
     // group all data in the result array, and remove unneeded `_id` field 
     { $group: { _id: null, result: { $push: "$result" }}},
     { $project: { _id: 0, result: 1}}
    ])
    

    制作:

    {
        "result" : [
            {
                "age" : [
                    {
                        "count" : 3,
                        "value" : "40"
                    },
                    {
                        "count" : 1,
                        "value" : "50"
                    }
                ]
            },
            {
                "childs" : [
                    {
                        "count" : 1,
                        "value" : "1"
                    },
                    {
                        "count" : 3,
                        "value" : "2"
                    }
                ]
            }
        ]
    }
    

    そして今、いくつかの説明のために:

    ここでの主要な問題の1つは、各受信ドキュメントが2つのの一部である必要があることです。 異なる合計。リテラル配列["age", "childs"]を追加することでそれを解決しました ドキュメントに追加し、その配列でそれらを巻き戻します。そうすれば、各ドキュメントが2回表示されます。 後の段階で。

    それが終わったら、処理を簡単にするために、データ表現を{ data: "age", value: "40" }のようなはるかに管理しやすいものに変更します。

    次の手順は、データ集約自体を実行します。 3番目までの$project 値フィールドを対応するageにマップするステップ またはchilds フィールド。

    最後の2つの手順では、2つのドキュメントを1つにまとめて、不要な_idを削除します。 フィールド。

    Pfff!




    1. Meteorで例を実行する際の問題

    2. キーを削除するにはどうすればよいですか?

    3. 埋め込み配列オブジェクトが変更されたときにMongooseインスタンス.save()が機能しない

    4. MongoError:このMongoDBデプロイメントは、再試行可能な書き込みをサポートしていません。接続文字列にretryWrites=falseを追加してください