首页 > 解决方案 > 如何在mongodb中查询多个集合?

问题描述

订阅集合:

{
    "_id":ObjectId("60924ec559bedd45dd74bd61"),
    "userID":ObjectId("6090f048536d345a024b8b60")
}

{
    "_id":ObjectId("609141bd392194fde3ba7cf6"),
    "userID":ObjectId("6090f048536d345a024b8b60")
}
{
    "_id":ObjectId("609141bd392194fde3ba7c54"),
    "userID":ObjectId("6090f048536d345a024b8bc2")
}

api集合:

{
   "_id":ObjectId("60924e7426ed2445aab2fc7f"),
   "subscriptionID":ObjectId("609143fb036c8a007a5e6a61")
}
{
   "_id":ObjectId("60924ec559bedd45dd74bd61"),
   "subscriptionID":ObjectId("609141bd392194fde3ba7cf6")
}
{
   "_id":ObjectId("60924ec559bedd45dd74bd68"),
   "subscriptionID":ObjectId("609141bd392194fde3ba7c54")
}

现在我想让所有api keys用户都使用userID

意味着我将通过Api collection find subscriptionID=> 然后go to the subscription collection和 =>match the userID with the provided userID

注意 - api 集合中的订阅 ID 是唯一的(订阅只有一个 api 密钥)用户 ID 在订阅集合中不是唯一的。

input: userID - 6090f048536d345a024b8b60
output:  first two api documents

标签: node.jsmongodbmongoose

解决方案


您实现 MongoDB 模式的方式是一种非常糟糕的做法。尝试将键嵌入到您想要直接引用其他集合的任何位置。

下面的查询可以工作,但如果要查找的记录数非常多,则会消耗大量时间。

db.getCollection('user').aggregate([
{
    "$match": {
        "_id" : {
            "$in": [
            ObjectId("6090f048536d345a024b8bc2"), 
            ObjectId("6090f048536d345a024b8b60")]
        }
    }
},
{
    "$lookup": {
        "from": "subscription",
        "let": {"u_id": "$_id"},
        "pipeline": [
            {
                "$match": {
                    "$expr": {
                        "$eq": ["$userID", "$$u_id"],
                    }
                }
            },
            {
                "$project": {
                    "_id": 1
                }
            },
        ],
        "as": "subscriptionData"
    }
},
{
    "$unwind": {
        "path": "$subscriptionData", 
        "preserveNullAndEmptyArrays": false,
    }
},
{
    "$lookup": {
        "from": "api",
        "let": {"sub_id": "$subscriptionData._id"},
        "pipeline": [
            {
                "$match": {
                    "$expr": {
                        "$eq": ["$subscriptionID", "$$sub_id"],
                    }
                }
            },
            {
                "$project": {
                    "_id": 1
                }
            },
        ],
        "as": "apiData"
    }
},
{
    "$unwind": {
        "path": "$apiData", 
        "preserveNullAndEmptyArrays": false,
    }
},
{
    "$group": {
        "_id": "$_id",
        "subscriptionIds": {"$addToSet": "$subscriptionData._id"},
        "apiIds": {"$addToSet": "$apiData._id"},
    },
},
])

此查询为提供的输入样本返回以下输出。

[
{
    "_id" : ObjectId("6090f048536d345a024b8b60"),
    "subscriptionIds" : [ 
        ObjectId("609141bd392194fde3ba7cf6")
    ],
    "apiIds" : [ 
        ObjectId("60924ec559bedd45dd74bd61")
    ]
},
{
    "_id" : ObjectId("6090f048536d345a024b8bc2"),
    "subscriptionIds" : [ 
        ObjectId("609141bd392194fde3ba7c54")
    ],
    "apiIds" : [ 
        ObjectId("60924ec559bedd45dd74bd68")
    ]
}
]

推荐阅读