1、lookup簡介
MongoDB作為一個nosql類型的數據庫,並沒有像關系型數據庫那樣有着非常強大的外鍵(表與表)關聯,但是MongoDB 3.2中增加了$lookup
這個很牛逼的操作符,能夠讓你實現多表關聯查詢,而且它被放到了aggregate
這種輕量級的pipeline框架上,一個字:牛
假設我們在devops庫中有一個hosts集合以及一個gameapp集合,我們的gameapp集合中的文檔host_id
字段關聯到了hosts
文檔的_id
字段。
2、模擬數據
// 進入到devops庫
use devops
// 插入數據
db.hosts.insertMany([
{host: 'hdss7-21', private_ip: '172.16.7.21', public_ip: '202.100.23.21', region_id: '杭州', status: true},
{host: 'hdss7-22', private_ip: '172.16.7.22', public_ip: '202.100.23.22', region_id: '杭州', status: true},
])
db.gameapp.insertMany([
{host_id:ObjectId('5ef070ee381fbaacea727429'), name: 'qysg10001', version: '37184', port: 80001},
{host_id:ObjectId('5ef070ee381fbaacea727429'), name: 'qysg10002', version: '37184', port: 80002},
{host_id:ObjectId('5ef070ee381fbaacea727429'), name: 'qysg10003', version: '37184', port: 80003},
{host_id:ObjectId('5ef070ee381fbaacea72742a'), name: 'qysg10004', version: '37184', port: 80004},
{host_id:ObjectId('5ef070ee381fbaacea72742a'), name: 'qysg10005', version: '37184', port: 80005},
{host_id:ObjectId('5ef070ee381fbaacea72742a'), name: 'qysg10006', version: '37184', port: 80006},
{host_id:ObjectId('5ef070ee381fbaacea72742a'), name: 'qysg10007', version: '37184', port: 80007},
])
// 驗證數據是否正確
db.hosts.find()
db.gameapp.find()
3、查詢操作
查詢指定游戲服所關聯的主機信息,最后只顯示主機的host、private_ip和status信息
1)$lookup使用
db.gameapp.aggregate([
{
$match: {name: 'qysg10001'}
},{
$lookup: {
from: 'hosts',
localField: 'host_id',
foreignField: '_id',
as: 'host_info'
}
}
])
簡單介紹$lookup
中的參數:
form:需要關聯的表(hosts)
localField:gameapp關聯到hosts的鍵(字段)
foreignField:hosts被關聯到gameapp的localField的鍵(字段)
as:對應的外鍵集合數據(可能存在一對多的情況)
返回的數據
{
"_id": ObjectId("5ef0737e381fbaacea727432"),
"host_id": ObjectId("5ef070ee381fbaacea727429"),
"name": "qysg10001",
"version": "37184",
"port": 80001,
"host_info": [{
"_id": ObjectId("5ef070ee381fbaacea727429"),
"host": "hdss7-21",
"private_ip": "172.16.7.21",
"public_ip": "202.100.23.21",
"region_id": "杭州",
"status": true
}]
}
2)可以看到host_info
返回元素裝在列表中,需要先把host_info
外層列表除去,通過$unwind
實現對host_info
拆分
db.gameapp.aggregate([
{
$match: {name: 'qysg10001'}
},{
$lookup: {
from: 'hosts',
localField: 'host_id',
foreignField: '_id',
as: 'host_info'
}
},{
$unwind: {
path: '$host_info',
preserveNullAndEmptyArrays: true,
}
}
])
返回數據:
{
"_id": ObjectId("5ef0737e381fbaacea727432"),
"host_id": ObjectId("5ef070ee381fbaacea727429"),
"name": "qysg10001",
"version": "37184",
"port": 80001,
"host_info": {
"_id": ObjectId("5ef070ee381fbaacea727429"),
"host": "hdss7-21",
"private_ip": "172.16.7.21",
"public_ip": "202.100.23.21",
"region_id": "杭州",
"status": true
}
}
3)現在通過$project
對數據進行過濾,我們只需要拿到host_info
下的host、private_ip和status信息
db.gameapp.aggregate([
{
$match: {name: 'qysg10001'}
},{
$lookup: {
from: 'hosts',
localField: 'host_id',
foreignField: '_id',
as: 'host_info'
}
},{
$unwind: {
path: '$host_info',
preserveNullAndEmptyArrays: true,
}
},{
$project: {
_id: 0,
'host_info.host': 1,
'host_info.private_ip': 1,
'host_info.status': 1,
}
}
])
返回結果:
{
"host_info":
{
"host": "hdss7-21",
"private_ip": "172.16.7.21",
"status": true
}
}