這篇我們來看mongodb另一個非常有意思的東西,那就是$lookup,我們知道mongodb是一個文件型的資料庫,而且它也是最像關係型資料庫的
一種nosql,但是呢,既然mongodb是無模式的,自然就很難在關係型資料庫中非常擅長的多表關聯上發揮作用,在這之前,我們可以使用DbRef,但
是呢,在mongodb 3.2 中給你增加了一個相當牛逼的手段,那就是$lookup,而且放到了aggreation這種重量級的pipeline分析框架上,自然就是一等
公民了,牛逼哈~。
一:介紹Aggregate
這個aggregate在mongodb中算是一個非常重量級的工具了,而且pipeline的管道模型的理論就是後面操作的資料來源來源於上一次操作的結果,這個
應該很好理解吧,好了,下面我們簡單看看aggreation中到底有哪幾個一等公民。
很簡單,就是上面的這十三個,比如說有了所謂的$group操作,我們就可以把這個aggreation做group的處理,有了$sort操作,就可以將結果進行排
序,有了$out操作,我們就可以將結果放到一個collections中去或者inline模式展示。。。
1. $lookup
說了這麼多,下面我們簡單的來演示一下,比如我們有一個product表,有一個orders表,自然就存在著一個外來鍵關係,下面我們就來造點資料。
db.product.insert({"_id":1,"productname":"商品1","price":15}) db.product.insert({"_id":2,"productname":"商品2","price":36}) db.orders.insert({"_id":1,"pid":1,"ordername":"訂單1"}) db.orders.insert({"_id":2,"pid":2,"ordername":"訂單2"}) db.orders.insert({"_id":3,"pid":2,"ordername":"訂單3"}) db.orders.insert({"_id":4,"pid":1,"ordername":"訂單4"}) db.product.find() db.orders.find()
好了,資料已經構造完畢,接下來我們要做的一個小需求就是,在orders表中,找到price of product >20 的訂單,這個需求看起來很簡單,對吧,
但是呢,我們的orders表中是沒有price的field的,所以第一步就是:
<1> $lookup 表關聯
1 db.product.aggregate([ 2 { 3 $lookup: 4 { 5 from: "orders", 6 localField: "_id", 7 foreignField: "pid", 8 as: "inventory_docs" 9 } 10 } 11 ])
然後展示的結果如下:
1 /* 1 */ 2 { 3 "_id" : 1.0, 4 "productname" : "商品1", 5 "price" : 15.0, 6 "inventory_docs" : [ 7 { 8 "_id" : 1.0, 9 "pid" : 1.0, 10 "ordername" : "訂單1" 11 }, 12 { 13 "_id" : 4.0, 14 "pid" : 1.0, 15 "ordername" : "訂單4" 16 } 17 ] 18 } 19 20 /* 2 */ 21 { 22 "_id" : 2.0, 23 "productname" : "商品2", 24 "price" : 36.0, 25 "inventory_docs" : [ 26 { 27 "_id" : 2.0, 28 "pid" : 2.0, 29 "ordername" : "訂單2" 30 }, 31 { 32 "_id" : 3.0, 33 "pid" : 2.0, 34 "ordername" : "訂單3" 35 } 36 ] 37 }
最後我放一張圖,這樣好眼見為實:
下面我簡單介紹一些$lookup中的引數:
from:需要關聯的表【orders】
localField: 【product】表需要關聯的鍵。
foreignField:【orders】的matching key。
as: 對應的外來鍵集合的資料,【因為可能是一對多的,對吧】
好了,表關聯已經做好了,接下來我們就需要用另外一個關鍵詞叫做$match,where條件的意思嘛。。。
<2> $match篩選
1 db.product.aggregate([ 2 { 3 $lookup: 4 { 5 from: "orders", 6 localField: "_id", 7 foreignField: "pid", 8 as: "inventory_docs" 9 } 10 }, 11 { $match : { price : {$gt:20} } } 12 ])
果然不出所料,我們就把”商品1“過濾掉了,因為它的價格小於20,對吧,但是呢,看起來還不是很完美,應為我只需要orders資訊,並不想要
所謂的product 這些屬性,這個時候我們就可以使用$project 做select操作了。。。
<3> $project 挑選欄位
接下來我們使用$project來指定我要獲取的欄位,比如我只需要inventory_docs欄位就可以了。
ok,當我執行之後,現在是這個吊樣子了,這個就是本篇所說的,是不是很簡單,同時呢,我也給大家簡單的介紹了下Aggreation的使用,是不
是很好玩,當然Aggregate下面還有其他很多的$操作符,你可以按照要求試試看哦~ 記得這個可是pipeline的模式哦。。。