mongodb多表查询(附带pymongo实例)

时间:2025-05-08 10:34:26

mongodb有$lookup可以做多表查询

举个例子

数据如下

db.orders.insert([
{ "_id" : , "item" : "almonds", "price" : , "quantity" : },
{ "_id" : , "item" : "pecans", "price" : , "quantity" : },
{ "_id" : }
])
db.inventory.insert([
{ "_id" : , "sku" : "almonds", description: "product 1", "instock" : },
{ "_id" : , "sku" : "bread", description: "product 2", "instock" : },
{ "_id" : , "sku" : "cashews", description: "product 3", "instock" : },
{ "_id" : , "sku" : "pecans", description: "product 4", "instock" : },
{ "_id" : , "sku": null, description: "Incomplete" },
{ "_id" : }
])

聚合操作如下

db.orders.aggregate([
{
$lookup:
{
from: "inventory",
localField: "item",
foreignField: "sku",
as: "inventory_docs"
}
},
])

上面的代码意思是,从order表中取item字段作为inventory表中sku的查询条件,然后把数据保存到inventory_docs字段,

等价于mysql中的

SELECT *, inventory_docs
FROM orders
WHERE inventory_docs IN (SELECT *
FROM inventory
WHERE sku= orders.item);

下面用pymongo实现

from pymongo import MongoClient

def test():
client = MongoClient()
db = client[db_name]
db['orders'].aggregate([{'$lookup':{'from': "inventory", "localField": "item", "foreignField": "sku", "as": "inventory_docs"}}])

这样就实现了上述的效果了

上述操作返回以下结果

{
"_id" : ,
"item" : "almonds",
"price" : ,
"quantity" : ,
"inventory_docs" : [
{ "_id" : , "sku" : "almonds", "description" : "product 1", "instock" : }
]
}
{
"_id" : ,
"item" : "pecans",
"price" : ,
"quantity" : ,
"inventory_docs" : [
{ "_id" : , "sku" : "pecans", "description" : "product 4", "instock" : }
]
}
{
"_id" : ,
"inventory_docs" : [
{ "_id" : , "sku" : null, "description" : "Incomplete" },
{ "_id" : }
]
}

看起来蛮方便的,但是其实很麻烦,如果我们只想显示inventory表中的某些字段,这样不符合我们的要求

这时候就需要用到$project和$arrayElemAt

如果我们只想显示inventory中的instock字段的话应该这样做

db.orders.aggregate([
{
$lookup:
{
from: "inventory",
localField: "item",
foreignField: "sku",
as: "inventory_docs"
}
},
{
$project:
{
'instock': {'$arrayElemAt':['$inventory_docs.instock', ]}
},
},
])

返回的结果是

{'_id': 1.0, 'instock': 120.0}
{'_id': 2.0, 'instock': 70.0}
{'_id': 3.0}

之前orders的数据好像没了,不用着急,在project里面添加想要返回的数据项即可

如我想要返回orders的price字段,在$project中添加{'price':1}即可,其他同

lookup更多详细用法

project可以指定返回的内容

 $project:
{
'sku':, 'item':,
}

指定返回sku和item

也可以重命名

$project:
{
'test': '$sku',
'item': ,
}

将sku字段重命名为test返回

https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/index.html