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

$graphLookupを使用したMongoでの階層クエリ

    レベルがあると信じています フィールド$reduceを使用して、配列から階層構造を構築できます。これを実現するには、reporteesを取得する必要があります $graphLookupの後にレベルの降順で並べ替えられます 。残念ながら、現在それを行う唯一の方法は、$ unwind + $ sort + $ groupを使用することです。これにより、集計が非常に長くなります。

    次に、$reduceを使用してその順序付けられた配列を処理できます 。各ステップで、従業員をreporteesを含む結果セットに追加する必要があります。 前のレベルから。さらに、levelを検出する必要があります 処理中に変更し、その場合はヘルパー配列を再配置します。

    $ addFieldsは、既存のreporteesを置き換えるだけです。 この場合のフィールド。 $ concatArraysを使用すると、現在の従業員を追加できます($$this )結果に。 $ filterを使用すると、reporteesを取得できます。 下位レベルから。

    db.getCollection('employees').aggregate([
        {
            $match: {
                empId : "10"
            }
        },
        {
            $graphLookup: {
                from: "employees",
                startWith: "$empId",
                connectFromField: "empId",
                connectToField: "managerId",
                as: "reportees",
                maxDepth: 4,
                depthField: "level"
            }
        },
        {
            $project: {
                "empId":1,
                "managerId":1,
                "reportees.empId":1,
                "reportees.name":1,
                "reportees.managerId":1,
                "reportees.level":1
            }
        },
        {
            $unwind: "$reportees"
        },
        {
            $sort: { "reportees.level": -1 }
        },
        {
            $group: {
                _id: "$_id",
                empId: { $first: "$empId" },
                managerId: { $first: "$managerId" },
                reportees: { $push: "$reportees" }
            }
        },
        {
            $addFields: {
                reportees: {
                    $reduce: {
                        input: "$reportees",
                        initialValue: {
                            currentLevel: -1,
                            currentLevelEmployees: [],
                            previousLevelEmployees: []
                        },
                        in: {
                            $let: {
                                vars: {
                                    prev: { 
                                        $cond: [ 
                                            { $eq: [ "$$value.currentLevel", "$$this.level" ] }, 
                                            "$$value.previousLevelEmployees", 
                                            "$$value.currentLevelEmployees" 
                                        ] 
                                    },
                                    current: { 
                                        $cond: [ 
                                            { $eq: [ "$$value.currentLevel", "$$this.level" ] }, 
                                            "$$value.currentLevelEmployees", 
                                            [] 
                                        ] 
                                    }
                                },
                                in: {
                                    currentLevel: "$$this.level",
                                    previousLevelEmployees: "$$prev",
                                    currentLevelEmployees: {
                                        $concatArrays: [
                                            "$$current", 
                                            [
                                                { $mergeObjects: [ 
                                                    "$$this", 
                                                    { reportees: { $filter: { input: "$$prev", as: "e", cond: { $eq: [ "$$e.managerId", "$$this.empId"  ] } } } } 
                                                ] }
                                            ]
                                        ]
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        {
            $addFields: { reportees: "$reportees.currentLevelEmployees" }
        }
    ]).pretty()
    

    上記のソリューションは、複数のレベルで機能するはずです。出力:

    {
        "_id" : "10",
        "empId" : "10",
        "managerId" : "15",
        "reportees" : [
            {
                "empId" : "6",
                "name" : "Employee6",
                "managerId" : "10",
                "level" : NumberLong(0),
                "reportees" : [
                    {
                            "empId" : "1",
                            "name" : "Employee1",
                            "managerId" : "6",
                            "level" : NumberLong(1),
                            "reportees" : [ ]
                    },
                    {
                            "empId" : "2",
                            "name" : "Employee2",
                            "managerId" : "6",
                            "level" : NumberLong(1),
                            "reportees" : [ ]
                    }
                ]
            },
            {
                "empId" : "8",
                "name" : "Employee8",
                "managerId" : "10",
                "level" : NumberLong(0),
                "reportees" : [
                    {
                        "empId" : "5",
                        "name" : "Employee5",
                        "managerId" : "8",
                        "level" : NumberLong(1),
                        "reportees" : [ ]
                    },
                    {
                        "empId" : "4",
                        "name" : "Employee4",
                        "managerId" : "8",
                        "level" : NumberLong(1),
                        "reportees" : [ ]
                    }
                ]
            }
        ]
    }
    


    1. 新しく作成したMongoDBインスタンスにデータをインポートします

    2. レスキュー:接続が拒否されました-localhost:6379でRedisに接続できません

    3. オープンソースデータベースを展開する方法

    4. Mongoでnullではないことをどのようにクエリしますか?