mongodb有$lookup可以做多表查詢
舉個例子
數據如下
db.orders.insert([ { "_id" : 1, "item" : "almonds", "price" : 12, "quantity" : 2 }, { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1 }, { "_id" : 3 } ]) db.inventory.insert([ { "_id" : 1, "sku" : "almonds", description: "product 1", "instock" : 120 }, { "_id" : 2, "sku" : "bread", description: "product 2", "instock" : 80 }, { "_id" : 3, "sku" : "cashews", description: "product 3", "instock" : 60 }, { "_id" : 4, "sku" : "pecans", description: "product 4", "instock" : 70 }, { "_id" : 5, "sku": null, description: "Incomplete" }, { "_id" : 6 } ])
聚合操作如下
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" : 1, "item" : "almonds", "price" : 12, "quantity" : 2, "inventory_docs" : [ { "_id" : 1, "sku" : "almonds", "description" : "product 1", "instock" : 120 } ] } { "_id" : 2, "item" : "pecans", "price" : 20, "quantity" : 1, "inventory_docs" : [ { "_id" : 4, "sku" : "pecans", "description" : "product 4", "instock" : 70 } ] } { "_id" : 3, "inventory_docs" : [ { "_id" : 5, "sku" : null, "description" : "Incomplete" }, { "_id" : 6 } ] }
看起來蠻方便的,但是其實很麻煩,如果我們只想顯示inventory表中的某些字段,這樣不符合我們的要求
這時候就需要用到$project和$arrayElemAt
如果我們只想顯示inventory中的instock字段的話應該這樣做
db.orders.aggregate([ { $lookup: { from: "inventory", localField: "item", foreignField: "sku", as: "inventory_docs" } }, { $project: { 'instock': {'$arrayElemAt':['$inventory_docs.instock', 0]} }, }, ])
返回的結果是
{'_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':1, 'item':1, }
指定返回sku和item
也可以重命名
$project: { 'test': '$sku', 'item': 1, }
將sku字段重命名為test返回
https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/index.html
