MongoDB 強大的連表查詢之$lookup


1、lookup簡介

MongoDB作為一個nosql類型的數據庫,並沒有像關系型數據庫那樣有着非常強大的外鍵(表與表)關聯,但是MongoDB 3.2中增加了$lookup這個很牛逼的操作符,能夠讓你實現多表關聯查詢,而且它被放到了aggregate這種輕量級的pipeline框架上,一個字:牛

Aggregation支持的操作符

假設我們在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 
	} 
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM