MongoDB
 sql >> Cơ Sở Dữ Liệu >  >> NoSQL >> MongoDB

Truy vấn phân cấp với Mongo bằng cách sử dụng $ graphLookup

Tôi tin rằng có cấp độ trường chúng ta có thể xây dựng cấu trúc phân cấp từ một mảng bằng cách sử dụng $ Reduce. Để đạt được điều đó, chúng ta cần có reportees được sắp xếp theo cấp độ giảm dần sau $graphLookup . Thật không may, cách duy nhất để làm điều đó hiện tại là sử dụng nhóm $ unwind + $ sort + $, điều này làm cho việc tổng hợp khá dài.

Sau đó, chúng tôi có thể xử lý mảng được sắp xếp đó bằng cách sử dụng $reduce . Trong mỗi bước, chúng tôi chỉ cần thêm một nhân viên vào tập kết quả bao gồm reportees của anh ta từ cấp độ trước. Ngoài ra, chúng tôi cần phát hiện khi nào level các thay đổi trong quá trình xử lý của chúng tôi và sắp xếp lại các mảng trợ giúp trong trường hợp đó.

$ addFields chỉ cần thay thế reportees trong trường hợp này. $ concatArrays cho phép chúng tôi thêm nhân viên hiện tại ($$this ) đến kết quả. Sử dụng bộ lọc $, chúng tôi có thể nhận được reportees từ cấp thấp hơn.

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()

Giải pháp trên sẽ hoạt động cho nhiều cấp độ. Kết quả đầu ra:

{
    "_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. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Tìm bản ghi mongoDB theo lô (sử dụng bộ điều hợp ruby ​​mongoid)

  2. MongoDB $ oid so với ObjectId

  3. $ unset trống. Bạn phải chỉ định một trường như vậy:{$ unset:{<field>:...}}

  4. Nhà điều hành đường ống tổng hợp cuối cùng MongoDB $

  5. Xác thực MongoDB 3.2 không thành công