使用 MongoDB 將兩個集合合併為一個集合

Mehvish Ashiq 2023年1月30日
  1. 使用 MongoDB 將兩個集合合併為一個集合
  2. 使用 $lookup 聚合階段將兩個集合合二為一
  3. 使用 pipeline 運算子根據指定條件將兩個集合合併為一個
  4. 在附加到結果文件之前使用 $unwind 運算子來平面陣列
  5. 在聚合查詢中使用 $project 過濾器階段將兩個集合合二為一
  6. 使用 Compass 連線兩個集合(MongoDB 的圖形介面)
使用 MongoDB 將兩個集合合併為一個集合

今天,我們將使用 $lookup 聚合階段、pipeline$unwind 運算子、$project 過濾階段和 MongoDB Compass 將兩個集合合併為一個集合。

使用 MongoDB 將兩個集合合併為一個集合

我們有不同的方法可以使用 MongoDB 將兩個集合組合成一個集合。其中一些在下面給出,我們將在本教程中介紹。

  1. 使用 $lookup 聚合階段加入兩個集合
  2. 使用 pipeline 運算子根據指定條件連線兩個集合
  3. 在將陣列附加到結果文件之前,使用 $unwind 運算子對陣列進行展平
  4. 在聚合查詢中使用 $project 過濾階段來連線兩個集合
  5. 使用指南針連線兩個集合(MongoDB 的圖形介面)

對於上述所有場景,我們必須有一個包含兩個集合(與 MySQL 中的表相同)的資料庫,其中填充了文件(與 MySQL 中的記錄相同)。我們使用以下查詢完成了這項工作;你也可以這樣做。

建立兩個名為 usersInformationuserAddress 的集合,它們位於 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 欄位中指定的集合的輸入文件的屬性(欄位)之一。

它用於對集合文件中的 localFieldforeignField 執行匹配。

類似地,名為 foreignField 的第三個欄位也對集合文件中的 foreignFieldlocalField 執行相等匹配。

我們為第四個欄位 as 寫下新陣列的名稱。有關 $lookup 聚合階段的說明,請參見以下說明。

使用 mongodb 將兩個集合合併為一個集合 - 查詢階段解釋

使用 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"
                }
        ]
}

當我們想要基於特定條件連線兩個集合時,我們可以使用帶有 $lookuppipeline 運算子(就像我們在 MySQL 中使用 WHERE 子句一樣)。

例如,我們正在加入來自 userAddressfullname 等於 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 連線起來,我們只希望連線 citystreet 欄位。

在這種情況下,我們需要使用 $addFields 階段。我們使用此階段將陣列/物件中的任何欄位或多個欄位加入/分配到文件的根級別。

因此,我們執行以下查詢以從 userAddress 集合中檢索 citystreet

示例程式碼:

> 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"
}

仔細關注上面給出的輸出。我們得到了街道城市嗎?是的,我們在文件的根級別獲得了 streetcity,但也有我們現在不需要的 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 物件,但它的兩個欄位(streetcity)被分配給文件的根級別。

使用 Compass 連線兩個集合(MongoDB 的圖形介面)

使用圖形介面進行聚合很容易。我們只需要在 $lookup 聚合階段執行以下步驟。

  1. 開啟 MongoDBCompass 並連線到伺服器。

  2. 如果需要,建立一個全新的資料庫和兩個集合。我們使用使用 Mongo shell 建立的相同資料庫和集合。

  3. 開啟你的集合,如下所示。

    使用 mongodb 將兩個集合合併為一個集合 - compass open collections

  4. 根據你的專案要求新增階段;我們新增了 $lookup 聚合階段。更新 $lookup 欄位並在右側檢視所需的結果。

    使用 mongodb 將兩個集合合併為一個集合–compass 新增查詢階段

作者: Mehvish Ashiq
Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

相關文章 - MongoDB Collection

相關文章 - MongoDB Join