如何通过factory_id关联查询MongoDB工厂文档并嵌入手机结果列表?
如何通过factory_id关联MongoDB中的phone和factory集合并嵌入工厂文档
问题背景
我使用Flask搭配Jinja2模板引擎,通过pymongo操作MongoDB。现有phone和factory两个集合的文档结构如下:
phone集合文档示例
phone = db.get_collection("phone")
{ "_id": ObjectId("63d8d39206c9f93e68d27206"), "brand": "Apple", "model": "iPhone XR", "year": NumberInt("2016"), "image": "https://apple-mania.com.ua/media/catalog/product/cache/e026f651b05122a6916299262b60c47d/a/p/apple-iphone-xr-yellow_1.png", "CPU": { "manufacturer": "A12 Bionic", "cores": NumberInt("10") }, "misc": [ "Bluetooth 5.0", "NFC", "GPS" ], "factory_id": ObjectId("63d8d42b7a4d7a7e825ef956") }
factory集合文档示例
factory = db.get_collection("factory")
{ "_id": ObjectId("63d8d42b7a4d7a7e825ef956"), "name": "Foxconn", "stock": NumberInt("1000") }
当前我的查询代码为:
models = list( phone.find({"brand": brand}, projection={"model": True, "image": True, "factory_id": True}) )
需要实现:通过factory_id获取关联的工厂文档,并将其作为嵌入式文档包含在models列表的每个手机对象中。
解决方案
方案1:使用MongoDB聚合查询($lookup)
利用MongoDB原生的$lookup操作符在数据库层面完成关联,效率更高,适合数据量较大的场景。
pipeline = [ # 筛选指定品牌的手机 {"$match": {"brand": brand}}, # 关联factory集合,匹配factory_id与_id {"$lookup": { "from": "factory", "localField": "factory_id", "foreignField": "_id", "as": "factory" }}, # 将关联结果的数组转为单个嵌入式文档(一对一关联场景) {"$unwind": "$factory"}, # 指定返回字段(按需调整) {"$project": { "model": 1, "image": 1, "factory": 1 }} ] models = list(phone.aggregate(pipeline))
说明:
$match:和原find逻辑一致,先过滤目标品牌的手机。$lookup:从factory集合中匹配与当前手机factory_id相等的文档,结果会存入factory数组。$unwind:因为每个手机只对应一个工厂,将数组展开为单个对象,方便后续使用。$project:控制最终返回的字段,这里保留手机的型号、图片,以及关联后的工厂文档。
方案2:Python层面手动关联查询
如果不想使用聚合,可通过Python代码手动完成关联,逻辑更直观,适合小数据量场景。
# 1. 查询指定品牌的手机,保留所需字段和factory_id models = list( phone.find({"brand": brand}, projection={"model": True, "image": True, "factory_id": True}) ) # 2. 提取所有factory_id,批量查询工厂并转为字典(以_id为键) factory_ids = [doc["factory_id"] for doc in models] factory_map = {f["_id"]: f for f in factory.find({"_id": {"$in": factory_ids}})} # 3. 将工厂文档嵌入对应手机对象 for doc in models: doc["factory"] = factory_map.get(doc["factory_id"])
说明:
- 第一步按原逻辑获取手机列表。
- 第二步批量查询所有关联的工厂,用字典存储可以避免多次查询,提升效率。
- 第三步遍历手机列表,将对应的工厂文档赋值到
factory字段中。
内容的提问来源于stack exchange,提问作者Vitalii Mytenko
相关产品推荐
相关产品推荐

