使用Node.js + Express + MongoDB从多个集合中获取数据 -lookup-
首先, 或者 先说一下
我們希望從works中提取數據,並根據user_id還提取相應的users數據。但是,當我們一次提取多個數據並進行合併時,使用MongoDB相對於MySQL來說似乎更難處理。經過一番研究後,我們發現MongoDB也有類似MySQL中的左連接(left join)的用法。
数据
{
"user_name": "king",
"age": 20,
"id": "admin",
"pw": "1234",
"role": "admin",
"department": "A"
}
{
"title": "to be hero",
"due_date": "2022-12-15",
"create_datetime": "2022-12-03 19:59:39",
"user_id": "admin"
}
首先尝试在lookup中提取。
db.collection("works").aggregate([
{
$lookup: {
from: "users",
localField: "user_id",
foreignField: "id",
as: "unserInfo"
},
},
]).toArray((err, result) => {
console.log(result)
res.render('./works/works.ejs', { works: result })
})
from: 対象のコレクション
localField: 結合に使用される基準のコレクションのフィールド(ここではworks)
foreignField: 結合に使用される対象のコレクションのフィールド(ここではusers)
as: 対象のコレクションのドキュメントの保存名
[
{
_id: new ObjectId("638b2c1b6c66bbaeee6c0aa6"),
title: 'to be hero',
due_date: '2022-12-15',
create_datetime: '2022-12-03 19:59:39',
user_id: 'admin',
unserInfo: [
{
_id: new ObjectId("6388ca58dbdf448d85e9e159"),
user_name: 'king',
age: 20,
id: 'admin',
pw: '1234',
role: 'admin',
department: 'A'
}
]
}
]
在获取工作数据的同时,还以用户信息的形式提取了userInfo。然而,userInfo中包含了用户对象数据的列表类型。
由于这样不方便使用,我们可以通过下一个$unwind操作,将对象从列表中提取出来。
从列表中提取
db.collection("works").aggregate([
{
$lookup: {
from: "users",
localField: "user_id",
foreignField: "id",
as: "unserInfo"
},
},
//追加
{ $unwind: "$unserInfo" },
]).toArray((err, result) => {
res.render('./works/works.ejs', { works: result })
})
[
{
_id: new ObjectId("638b2c1b6c66bbaeee6c0aa6"),
title: 'to be hero',
due_date: '2022-12-15',
create_datetime: '2022-12-03 19:59:39',
user_id: 'admin',
unserInfo: {
_id: new ObjectId("6388ca58dbdf448d85e9e159"),
user_name: 'king',
age: 20,
id: 'admin',
pw: '1234',
role: 'admin',
department: 'A'
}
}
]
通过使用 $unwind,从列表中提取出来。
如果贪心一点,还想从对象中提取出来。
从对象中提取出来使用 $project。
合并必需的字段
db.collection("works").aggregate([
{
$lookup: {
from: "users",
localField: "user_id",
foreignField: "id",
as: "unserInfo"
},
},
{ $unwind: "$unserInfo" },
{
//追加
$project: {
_id: 1,
create_datetime: 1,
user_id: 1,
user_name: "$unserInfo.user_name",
role: "$unserInfo.role",
}
}
]).toArray((err, result) => {
res.render('./works/works.ejs', { works: result })
})
[
{
_id: new ObjectId("638b2c1b6c66bbaeee6c0aa6"),
create_datetime: '2022-12-03 19:59:39',
user_id: 'admin',
user_name: 'king',
role: 'admin'
}
]
可以通过指定原始字段的基准值为1来显示。
在合并数据时,需要指定新旧字段。
然而,似乎还没有一种无需指定即可列出所有字段的方法。
最后
很遺憾,目前好像還沒有像MySQL那樣完美的left join。
我覺得無法直接使用SQL語句是MongoDB的缺點。
但是如果能夠像使用inner join那樣的方式,我覺得開發速度會加快。
相关