掌握MongoDB多表關聯查詢的技巧

引言

MongoDB是一個非關係型資料庫,大受歡迎的原因之一是很方便在多個集合(就是”表”的概念)中進行聯合查詢。

如果你是初學者,那麼你可能會問什麼時候需要聯合查詢。舉個例子,如果你有一個學生集合和一個成績集合,你可能會想要查詢一個學生所有課程的成績。

本文將介紹如何使用MongoDB進行多表聯合查詢,包括內嵌文檔和$lookup操作符兩種方法。

內嵌文檔

內嵌文檔是MongoDB中最基本且最常見的多表聯合查詢方法。

小標題1:內嵌文檔基礎

首先,需要知道如何在一個文檔中嵌入其他文檔。這個操作可以使用Mongo Shell或任何MongoDB操作客戶端。這裡使用Mongo Shell作為演示。

> db.students.insert({
    "name": "小明",
    "age": 20,
    "score": {
        "math": 80,
        "chinese": 90,
        "english": 85
    }
})

上面這個例子將一個名為”小明”的學生文檔插入了學生集合中。此文檔有一個嵌套的分數文檔。

接下來,我們將展示如何查詢學生的成績記錄:

> db.students.find({"name": "小明"})
{ "_id" : ObjectId("60efa25968ca5ef8843f0c0c"), "name" : "小明", "age" : 20, "score" : { "math" : 80, "chinese" : 90, "english" : 85 } }

很簡單,只需要將查詢條件指定為”name”為”小明”即可。

小標題2:多個文檔的聯合查詢

接下來,我們將學生文檔和成績文檔嵌入一個班級文檔,以此演示如何使用內嵌文檔查詢多個文檔:

> db.classes.insert({
    "name": "一年級",
    "students": [
        {
            "name": "小明",
            "age": 20,
            "score": {
                "math": 80,
                "chinese": 90,
                "english": 85
            }
        },
        {
            "name": "小紅",
            "age": 19,
            "score": {
                "math": 78,
                "chinese": 88,
                "english": 86
            }
        }
    ]
})

上面這個例子將一個名為”一年級”的班級文檔插入了班級集合中。此文檔有一個嵌套的學生文檔數組,數組裡包含兩個學生文檔,每個學生文檔有一個嵌套的成績文檔。

接下來,我們將展示如何查詢這個班級里所有學生的姓名和成績記錄:

> db.classes.find({}, {"students.name": 1, "students.score": 1})
{ "_id" : ObjectId("60efa5c068ca5ef8843f0c0d"), "students" : [ { "name" : "小明", "score" : { "math" : 80, "chinese" : 90, "english" : 85 } }, { "name" : "小紅", "score" : { "math" : 78, "chinese" : 88, "english" : 86 } } ] }

只需將查詢條件指定為一個空文檔,然後指定需要返回的欄位即可。在這個例子中,我們指定了”name”和”score”兩個欄位。

$lookup操作符

$lookup操作符是MongoDB中用於執行多表聯合查詢的最強大且最靈活的方法。

小標題1:單個查詢

首先,我們需要知道如何使用$lookup操作符查詢單個文檔中包含的多個子文檔。這個操作將會使用到餐廳和菜品兩個文檔。

> db.restaurants.insert({
    "name": "餐廳1",
    "dishes": [
        {
            "name": "紅燒肉",
            "price": 28
        },
        {
            "name": "魚香肉絲",
            "price": 18
        }
    ]
})

上面這個例子將一個名為”餐廳1″的餐廳文檔插入了餐廳集合中。此文檔有一個嵌套的菜品文檔數組,數組裡包含兩個菜品文檔。

接下來,我們將展示如何查詢一個餐廳,並將其菜品信息一併返回:

> db.restaurants.aggregate([
    {
        $match: {"name": "餐廳1"}
    },
    {
        $lookup: {
            from: "dishes",
            localField: "dishes.name",
            foreignField: "name",
            as: "dishes"
        }
    },
    {
        $project: {"dishes.name": 1, "dishes.price": 1}
    }
])

這是一個比較複雜的查詢,需要使用聚合管道(aggregate pipeline)來實現。首先使用$match操作符找到名稱為”餐廳1″的餐廳文檔,並將其作為管道的第一個操作。

然後,使用$lookup操作符查找”dishes”集合,並將其結果嵌入”restaurants”文檔中。$lookup操作符需要指定四個參數:

  • from:需要聯結的文檔集合名
  • localField:連接到當前文檔的本地鍵欄位
  • foreignField:連接到目標文檔的外鍵欄位
  • as:聯結到當前文檔的新鍵名

最後使用$project操作符將$dishes數組中的”name”和”price”欄位投影出來。

小標題2:多個查詢

現在,我們將舉一個更複雜的例子,使用$lookup操作符查詢多個文檔的聯合結果。這個例子將使用到學生、成績和課程三個文檔。

首先,我們需要在Mongo Shell中插入所有的測試文檔:

> db.students.insertMany([
    {"name": "小明", "age": 20},
    {"name": "小紅", "age": 19}
])
> db.courses.insertMany([
    {"name": "math", "credit": 3},
    {"name": "chinese", "credit": 3},
    {"name": "english", "credit": 2}
])
> db.scores.insertMany([
    {"student": "小明", "course": "math", "score": 80},
    {"student": "小明", "course": "chinese", "score": 90},
    {"student": "小明", "course": "english", "score": 85},
    {"student": "小紅", "course": "math", "score": 78},
    {"student": "小紅", "course": "chinese", "score": 88},
    {"student": "小紅", "course": "english", "score": 86}
])

接下來,我們將展示如何使用$lookup操作符查詢所有學生的所有成績和對應的課程信息:

> db.students.aggregate([
    {
        $lookup: {
            from: "scores",
            localField: "name",
            foreignField: "student",
            as: "scores"
        }
    },
    {
        $unwind: "$scores"
    },
    {
        $lookup: {
            from: "courses",
            localField: "scores.course",
            foreignField: "name",
            as: "course_info"
        }
    },
    {
        $unwind: "$course_info"
    },
    {
        $project: {"name": 1, "course": "$course_info.name", "credit": "$course_info.credit", "score": "$scores.score"}
    }
])

這是一個相對複雜的查詢,以便演示如何在多個MongoDB文檔中執行聯合查詢。

首先,使用$lookup操作符將”students”文檔和”scores”文檔聯結起來。將”students.name”欄位和”scores.student”欄位匹配。聯結結果將插入到”students.scores”數組中。

然後,使用$unwind操作符展開”students.scores”數組,以便進行下一步聯結。這裡使用了兩次$unwind,因為後續還會有一個聯結操作。

接下來,使用$lookup操作符將課程信息加入聯結結果中。將”students.scores.course”欄位和”courses.name”欄位匹配。聯結結果將插入到”students.scores.course_info”數組中。

最後,使用$project操作符來投影出我們想要的結果。在這個例子中,我們將”name”、”course”、”credit”和”score”欄位都投影出來。

結論

本文介紹了MongoDB中的兩種多表聯合查詢方法:內嵌文檔和$lookup操作符。內嵌文檔可以很容易地在一個文檔中嵌入其他文檔,但是只適用於簡單的聯合查詢場景。$lookup操作符則可以在多個MongoDB文檔之間執行更為靈活和複雜的聯合查詢。這些方法都可以用於多個領域,例如學生成績、餐廳菜品和體育比賽信息等。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/240369.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 12:21
下一篇 2024-12-12 12:21

相關推薦

  • 使用vscode建立UML圖的實踐和技巧

    本文將重點介紹在使用vscode在軟體開發中如何建立UML圖,並且給出操作交互和技巧的指導。 一、概述 在軟體開發中,UML圖是必不可少的重要工具之一。它為軟體架構和各種設計模式的…

    編程 2025-04-29
  • 優秀周記1000字的撰寫思路與技巧

    優秀周記是每個編程開發工程師記錄自己工作生活的最佳方式之一。本篇文章將從周記的重要性、撰寫思路、撰寫技巧以及周記的示例代碼等角度進行闡述。 一、周記的重要性 作為一名編程開發工程師…

    編程 2025-04-28
  • 堆疊圖配色技巧分享

    堆疊圖是數據可視化中常用的一種表現形式,而配色則是影響堆疊圖觀感和傳達信息的重要因素之一。本文將分享一些堆疊圖配色的技巧,幫助你創造更好的數據可視化。 一、色彩搭配原則 色彩是我們…

    編程 2025-04-27
  • 使用uring_cmd提高開發效率的技巧

    對於編程開發工程師來說,提高效率一直是致力追求的目標。本文將深度解析如何使用uring_cmd,提升工作效率。 一、常用命令 uring_cmd是一個非常強大的命令行工具,但是大部…

    編程 2025-04-27
  • 通信專業Python和Java的開發技巧

    本文旨在介紹通信專業Python和Java的開發技巧,為讀者提供實用且可操作的思路和方法。 一、Python在通信領域中的應用 Python是一種優秀的程序設計語言,因其易學易用、…

    編程 2025-04-27
  • 前端引用字體的實現方法和技巧

    對於前端開發人員而言,字體關系著網站的整體美觀度和用戶體驗。為了滿足客戶,開發人員經常需要引用特定的字體。在這篇文章中,我們將會詳細解決前端引用字體的實現方法和技巧。 一、字體引用…

    編程 2025-04-27
  • if not in case – Python中使用if語句進行邏輯判斷的技巧

    if語句是Python中進行邏輯判斷的基礎語句之一。在if語句中,我們可以使用not關鍵字和in關鍵字來進行更加靈活的判斷。本文將詳細介紹Python中使用if not in ca…

    編程 2025-04-27
  • JavaScript中修改style屬性的方法和技巧

    一、基本概念和方法 style屬性是JavaScript中一個非常重要的屬性,它可以用來控制HTML元素的樣式,包括顏色、大小、字體等等。這裡介紹一些常用的方法: 1、通過Java…

    編程 2025-04-25
  • Python連接MongoDB資料庫

    MongoDB是一個流行的開源、非關係型、文檔型資料庫。Python具有簡單、易學的語法、廣泛的應用能力,因此它很適合連接MongoDB資料庫。本文將從以下幾個方面詳細討論Pyth…

    編程 2025-04-25
  • Android文件讀取技巧:如何快速獲取文件內容

    在Android開發中,讀取文件是非常常見的操作。然而,在某些情況下,如果讀取文件的操作不夠高效,會導致程序出現卡頓、耗時等問題。因此,在本篇文章中,我們將介紹一些Android文…

    編程 2025-04-25

發表回復

登錄後才能評論