MongoDB多次查找到同一集合

时间:2021-02-04 06:50:17

标签: sql mongodb join mongodb-query

我有两个集合 BillEmployee。 Bill 包含有关每月学生账单的信息,Employee 包含在学校工作的所有类型的人员(会计、教师、维护人员等)。
Bill 有 billVerifyByclassteacher 字段,它们指向员工的记录。
票据收集

{
    "_id": ObjectId("ab12dns..."),  //mongoid
    "studentname": "demoUser",
    "class": { "section": "A"},
    "billVerifiedBy": "121212",
    "classteacher": "134239",

}

员工合集

{
    "_id": ObjectId("121212"), // random number
    "name": "Darn Morphy",
    "department": "Accounts",
    "email": "dantest@test.com",
}

{
    "_id": ObjectId("134239"),
    "name": "Derreck",
    "department": "Faculty",
    "email": "derrect145@test.com",
}

我需要检索与特定账单相关的帐户和教师信息。我正在使用 Mongodb 查找来获取信息。但是,我必须两次查找同一个表,因为 billVerifiedBy 和 classteacher 属于下面给出的同一个 Employee 表。

db.bill.aggregate([  
    {
        $lookup: {"from": "employee", "localField": "billVerifiedBy", "foreignField": "_id", "as": "accounts"}},
    },
    {
        $lookup: {"from": "employee", "localField": "classteacher", "foreignField": "_id", "as": "faculty"}},
    },
    {
        $project: {
            "studentname": 1, 
            "class": 1,
            "verifiedUser": "$accounts.name",
            "verifiedByEmail":"$accounts.email",
            "facultyName": "$faculty.name",
            "facultyEmail": "$faculty.email"
        }
    }
]

我不知道这是否是在单个 Employee 集合中排列 Accounts 和 Faculty 信息的好方法。用同一个集合查找两次是否正确。或者我应该创建单独的 Accounts 和 Faculty 集合并使用它进行查找。请建议在性能方面最好的方法是什么。

1 个答案:

答案 0 :(得分:0)

在 mongodb 中,当你想加入来自同一个集合的多个文档时,你可以使用“$lookup”及其“pipeline”和“let”选项。它过滤您想要使用已定义变量获取的文档。

db.getCollection('Bill').aggregate([{
        "$lookup": {
            "as": "lookupUsers",
            "from": "Employee",
            // define variables that you need to use in pipeline to filter documents
            "let": {
                "verifier": "$billVerifiedBy",
                "teacher": "$classteacher"
            },
            "pipeline": [{ // filter employees who you need to filter.
                    "$match": {
                        "$expr": {
                            "$or": [{
                                    "$eq": ["$_id", "$$verifier"]
                                },
                                {
                                    "$eq": ["$_id", "$$teacher"]
                                }
                            ]
                        }
                    }
                },

                { // combine filtered 2 documents in an employee array
                    "$group": {
                        "_id": "",
                        "employee": {
                            "$addToSet": {
                                "_id": "$_id",
                                "name": "$name",
                                "department": "$department",
                                "email": "$email"
                            }
                        }
                    }
                },
                { // takes item from the array by predefined variable.
                    "$project": {
                        "_id": 0,
                        "billVerifiedBy": {
                            "$slice": [{
                                    "$filter": {
                                        "input": "$employee",
                                        "cond": {
                                            "$eq": ["$$this._id", "$$verifier"]
                                        }
                                    }
                                },
                                1
                            ]
                        },
                        "classteacher": {
                            "$slice": [{
                                    "$filter": {
                                        "input": "$employee",
                                        "cond": {
                                            "$eq": ["$$this._id", "$$teacher"]
                                        }
                                    }
                                },
                                1
                            ]
                        }
                    }
                },
                {
                    "$unwind": "$billVerifiedBy"
                },
                {
                    "$unwind": "$classteacher"
                },
            ]
        }
    },
    {
        "$unwind": "$lookupUsers"
    },
]);

输出是这样的:

{
    "_id": ObjectId("602916dcf4450742cdebe38d"),
    "studentname": "demoUser",
    "class": {
        "section": "A"
    },
    "billVerifiedBy": ObjectId("6029172e9ea6c9d4776517ce"),
    "classteacher": ObjectId("6029172e9ea6c9d4776517cf"),
    "lookupUsers": {
        "billVerifiedBy": {
            "_id": ObjectId("6029172e9ea6c9d4776517ce"),
            "name": "Darn Morphy",
            "department": "Accounts",
            "email": "dantest@test.com"
        },
        "classteacher": {
            "_id": ObjectId("6029172e9ea6c9d4776517cf"),
            "name": "Derreck",
            "department": "Faculty",
            "email": "derrect145@test.com"
        }
    }
}