使用 MongoDB 將兩個集合合併為一個集合
- 使用 MongoDB 將兩個集合合併為一個集合
-
使用
$lookup
聚合階段將兩個集合合二為一 -
使用
pipeline
運算子根據指定條件將兩個集合合併為一個 -
在附加到結果文件之前使用
$unwind
運算子來平面陣列 -
在聚合查詢中使用
$project
過濾器階段將兩個集合合二為一 - 使用 Compass 連線兩個集合(MongoDB 的圖形介面)
今天,我們將使用 $lookup
聚合階段、pipeline
和 $unwind
運算子、$project
過濾階段和 MongoDB Compass 將兩個集合合併為一個集合。
使用 MongoDB 將兩個集合合併為一個集合
我們有不同的方法可以使用 MongoDB 將兩個集合組合成一個集合。其中一些在下面給出,我們將在本教程中介紹。
- 使用
$lookup
聚合階段加入兩個集合 - 使用
pipeline
運算子根據指定條件連線兩個集合 - 在將陣列附加到結果文件之前,使用
$unwind
運算子對陣列進行展平 - 在聚合查詢中使用
$project
過濾階段來連線兩個集合 - 使用指南針連線兩個集合(MongoDB 的圖形介面)
對於上述所有場景,我們必須有一個包含兩個集合(與 MySQL 中的表相同)的資料庫,其中填充了文件(與 MySQL 中的記錄相同)。我們使用以下查詢完成了這項工作;你也可以這樣做。
建立兩個名為 usersInformation
和 userAddress
的集合,它們位於 users
資料庫中。此外,使用以下文件填充它們。
建立資料庫和集合:
> use users
> db.createCollection('userInformation')
> db.createCollection('userAddress')
用兩個文件填充 userInformation
集合:
> db.userInformation.insertMany(
[
{
fullname: 'Mehvish Ashiq',
age: 30,
gender: 'Female',
nationality: 'Pakistani'
},
{
fullname: 'James Daniel',
age: 45,
sex: 'male',
nationality: 'Canadian'
}
]
)
用兩個文件填充 userAddress
集合:
> db.userAddress.insertMany(
[
{
fullname: 'Mehvish Ashiq',
block_number: 22,
street: 'Johar Town Street',
city: 'Lahore'
},
{
fullname: 'James Daniel',
block_number: 30,
street: 'Saint-Denis Street',
city: 'Montreal'
}
]
)
我們使用 insertMany()
函式插入多個文件。現在,我們可以使用下面的命令來檢視兩個集合的資料。
在下面的程式碼片段中,pretty()
方法顯示了乾淨且格式化的輸出,這在 shell 上很容易理解。
顯示來自 userInformation
的文件:
> db.userInformation.find().pretty()
輸出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian"
}
顯示來自 userAddress
的文件:
> db.userAddress.find().pretty()
輸出:
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
兩個集合必須在同一個資料庫中才能使用 $lookup
聚合階段。一旦兩個集合都準備好了,我們可以根據我們的場景使用各種查詢來連線兩個集合的資料。
使用 $lookup
聚合階段將兩個集合合二為一
示例程式碼:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
}
]).pretty();
輸出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
]
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
]
}
在 MongoDB 資料庫中,$lookup
聚合階段執行與其他集合的左外連線,並從連線的文件中過濾資訊(資料)。例如,我們使用查詢來獲取所有使用者的資訊及其地址。
$lookup
函式接受四個欄位。首先是 from
欄位,我們在其中指定應該與另一個集合連線的集合。
第二個是 localField
欄位。它是 from
欄位中指定的集合的輸入文件的屬性(欄位)之一。
它用於對集合文件中的 localField
與 foreignField
執行匹配。
類似地,名為 foreignField
的第三個欄位也對集合文件中的 foreignField
與 localField
執行相等匹配。
我們為第四個欄位 as
寫下新陣列的名稱。有關 $lookup
聚合階段的說明,請參見以下說明。
使用 pipeline
運算子根據指定條件將兩個集合合併為一個
示例程式碼:
> db.userInformation.aggregate([{
$lookup:{
from: 'userAddress',
let: {full_name: '$fullname'},
pipeline: [{
$match: {
$expr: {
$eq: ['$fullname', '$$full_name']
}
}
}],
as: 'addressInfo'
}
}]).pretty()
輸出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"addressInfo" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
]
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"addressInfo" : [
{
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
]
}
當我們想要基於特定條件連線兩個集合時,我們可以使用帶有 $lookup
的 pipeline
運算子(就像我們在 MySQL 中使用 WHERE
子句一樣)。
例如,我們正在加入來自 userAddress
的 fullname
等於 userInformation
中的 fullname
的集合。
在附加到結果文件之前使用 $unwind
運算子來平面陣列
示例程式碼:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
}
]).pretty();
輸出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
}
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
}
$unwind
運算子什麼也不做,只是在將陣列附加到結果文件之前將其展平。 $unwind
運算子的根本區別在於它將具有單個元素的陣列轉換為扁平物件,即元素本身。
請記住,此元素的名稱不會更改。當元素為陣列形式時,它與以前相同。
使用和不使用 $unwind
運算子執行上述查詢並觀察 address
欄位。
在聚合查詢中使用 $project
過濾器階段將兩個集合合二為一
在使用 $project
加入集合之前,讓我們瞭解它的重要性。例如,如果我們不想將名為 userAddress
的整個集合與 userInformation
連線起來,我們只希望連線 city
和 street
欄位。
在這種情況下,我們需要使用 $addFields
階段。我們使用此階段將陣列/物件中的任何欄位或多個欄位加入/分配到文件的根級別。
因此,我們執行以下查詢以從 userAddress
集合中檢索 city
和 street
。
示例程式碼:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
},
{
$addFields: {
street: '$address.street',
city: '$address.city'
}
}
]).pretty();
輸出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"nationality" : "Pakistani",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a568"),
"fullname" : "Mehvish Ashiq",
"block_number" : 22,
"street" : "Johar Town Street",
"city" : "Lahore"
},
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"sex" : "male",
"nationality" : "Canadian",
"address" : {
"_id" : ObjectId("628bc4ae5c544feccff5a569"),
"fullname" : "James Daniel",
"block_number" : 30,
"street" : "Saint-Denis Street",
"city" : "Montreal"
},
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
仔細關注上面給出的輸出。我們得到了街道
和城市
嗎?是的,我們在文件的根級別獲得了 street
和 city
,但也有我們現在不需要的 address
物件。
這就是 $project
過濾階段的用武之地。它指定我們應該在結果文件中包含哪些欄位。
請參閱以下查詢以獲得更好的理解。
示例程式碼:
> db.userInformation.aggregate([
{ $lookup:
{
from: 'userAddress',
localField: 'fullname',
foreignField: 'fullname',
as: 'address'
}
},
{
$unwind: '$address'
},
{
$addFields: {
street: '$address.street',
city: '$address.city'
}
},
{
$project: {
fullname: 1,
age: 1,
gender: 1,
street: 1,
city: 1
}
}
]).pretty();
輸出:
{
"_id" : ObjectId("628bc4a45c544feccff5a566"),
"fullname" : "Mehvish Ashiq",
"age" : 30,
"gender" : "Female",
"street" : "Johar Town Street",
"city" : "Lahore"
}
{
"_id" : ObjectId("628bc4a45c544feccff5a567"),
"fullname" : "James Daniel",
"age" : 45,
"street" : "Saint-Denis Street",
"city" : "Montreal"
}
如你所見,我們現在沒有 address
物件,但它的兩個欄位(street
和 city
)被分配給文件的根級別。
使用 Compass 連線兩個集合(MongoDB 的圖形介面)
使用圖形介面進行聚合很容易。我們只需要在 $lookup
聚合階段執行以下步驟。
-
開啟
MongoDBCompass
並連線到伺服器。 -
如果需要,建立一個全新的資料庫和兩個集合。我們使用使用 Mongo shell 建立的相同資料庫和集合。
-
開啟你的集合,如下所示。
-
根據你的專案要求新增階段;我們新增了
$lookup
聚合階段。更新$lookup
欄位並在右側檢視所需的結果。