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

Spring MongoDB AggregationでDBRefをどのようにプロジェクトしますか?

    1。 MongoDBバージョン3.4の場合

    これらは、ユースケースを再現するために私が作成した次のコレクションです。

    アラートコレクション

    { 
        "_id" : ObjectId("59e6ff3d9ef9d46a91112890"), 
        "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
        "level" : "INFO", 
        "title" : "Alerta de Prueba", 
        "payload" : "Alerta de Prueba", 
        "create_at" : ISODate("2017-10-18T07:13:45.091+0000"), 
        "delivery_mode" : "PUSH_NOTIFICATION", 
        "delivered" : false, 
        "parent" : DBRef("parents", ObjectId("59e6ff369ef9d46a91112878")), 
        "son" : DBRef("children", ObjectId("59e72ff0572ae72d8c063666"))
    }
    { 
        "_id" : ObjectId("59e6ff6d9ef9d46a91112892"), 
        "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
        "level" : "WARNING", 
        "title" : "Token de acceso inv�lido.", 
        "payload" : "El token de acceso YOUTUBE no es valido", 
        "create_at" : ISODate("2017-10-18T07:14:53.449+0000"), 
        "delivery_mode" : "PUSH_NOTIFICATION", 
        "delivered" : false, 
        "parent" : DBRef("parents", ObjectId("59e6ff369ef9d46a91112878")), 
        "son" : DBRef("children", ObjectId("59e72ff0572ae72d8c063666"))
    }
    { 
        "_id" : ObjectId("59e6ff6d9ef9d46a91112893"), 
        "_class" : "es.bisite.usal.bulltect.persistence.entity.AlertEntity", 
        "level" : "WARNING", 
        "title" : "Token de acceso inv�lido.", 
        "payload" : "El token de acceso INSTAGRAM no es v�lido", 
        "create_at" : ISODate("2017-10-18T07:14:53.468+0000"), 
        "delivery_mode" : "PUSH_NOTIFICATION", 
        "delivered" : false, 
        "parent" : DBRef("parents", ObjectId("59e6ff369ef9d46a91112878")), 
        "son" : DBRef("children", ObjectId("59e72ffb572ae72d8c063669"))
    }
    

    作成した子コレクションと一致するように、sons参照のOBjectIdsを変更したことに注意してください。

    子供向けコレクション

    { 
        "_id" : ObjectId("59e72ff0572ae72d8c063666"), 
        "name" : "Bob"
    }
    { 
        "_id" : ObjectId("59e72ffb572ae72d8c063669"), 
        "name" : "Tim"
    }
    

    参照を使用しているため、他のコレクションのフィールドにアクセスすることはできません。ですから、いくつかの集計手順が欠けていると思います。

    私は次のことをしました:

    db.getCollection('alerts').aggregate(
    {
                $unwind:"$son"
            },
            {
                $group:
                {
                    _id:{
                        son: "$son",
                        level: "$level"
                    },
                    count: { $sum: 1 }
                }
            },
            {
                $group:
                    {
                        _id:{ 
                            son: "$_id.son"
                        },
                        alerts: { $addToSet: {
                            level: "$_id.level",
                            count: "$count"
                        }}
    
                    }
             },
            { $addFields: { sonsArray: { $objectToArray: "$_id.son" } } },
            { $match: { "sonsArray.k": "$id"}  },
            { $lookup: { from: "children", localField: "sonsArray.v", foreignField: "_id", as: "name" } }
    )
    

    そして、jsonとして次の結果が得られました:

    { 
        "_id" : {
            "son" : DBRef("children", ObjectId("59e72ffb572ae72d8c063669"))
        }, 
        "alerts" : [
            {
                "level" : "WARNING", 
                "count" : NumberInt(1)
            }
        ], 
        "sonsArray" : [
            {
                "k" : "$ref", 
                "v" : "children"
            }, 
            {
                "k" : "$id", 
                "v" : ObjectId("59e72ffb572ae72d8c063669")
            }
        ], 
        "name" : [
            {
                "_id" : ObjectId("59e72ffb572ae72d8c063669"), 
                "name" : "Tim"
            }
        ]
    }
    { 
        "_id" : {
            "son" : DBRef("children", ObjectId("59e72ff0572ae72d8c063666"))
        }, 
        "alerts" : [
            {
                "level" : "INFO", 
                "count" : NumberInt(1)
            }, 
            {
                "level" : "WARNING", 
                "count" : NumberInt(1)
            }
        ], 
        "sonsArray" : [
            {
                "k" : "$ref", 
                "v" : "children"
            }, 
            {
                "k" : "$id", 
                "v" : ObjectId("59e72ff0572ae72d8c063666")
            }
        ], 
        "name" : [
            {
                "_id" : ObjectId("59e72ff0572ae72d8c063666"), 
                "name" : "Bob"
            }
        ]
    }
    

    sonsArrayなどのように追加で作成されたフィールドを削除したい場合は、$projectを追加できます。 cleanへのパイプライン あなたの結果。

    2。古いバージョンのmongodbを使用していて、データ構造を変更できる場合。

    このような参照を使用する代わりに:

    "son" : DBRef("children", ObjectId("59e72ffb572ae72d8c063669"))
    

    息子のobjectIdを次のような配列として追加できます:

    "sonId" : [
            ObjectId("59e72ff0572ae72d8c063666")
        ]
    

    次に、次のように集計を行うことができます。

    db.getCollection('alerts').aggregate(
    {
                $unwind:"$sonId"
            },
            {
                $group:
                {
                    _id:{
                        sonId: "$sonId",
                        level: "$level"
                    },
                    count: { $sum: 1 }
                }
            },
            {
                $group:
                    {
                        _id:{ 
                            sonId: "$_id.sonId"
                        },
                        alerts: { $addToSet: {
                            level: "$_id.level",
                            count: "$count"
                        }}
    
                    }
             },
            { $lookup: { from: "children", localField: "_id.sonId", foreignField: "_id", as: "son" } }
    )
    

    それはあなたが探しているものですか?




    1. BIGコレクションでのフィルタリングと並べ替えのためのMongodb複合インデックス

    2. 推奨事項を支援するMongoDB

    3. mongodbアグリゲーションでのルックアップ

    4. MongoDBのクエリからさらに結果があるかどうかを確認するにはどうすればよいですか?