HOWTO · MongoDB
MongoDB 巢狀欄位投影
本指南說明如何使用點記法搭配 find() 選取 MongoDB 巢狀欄位、使用 $project 調整聚合結果的形狀,以及使用 $unset 移除欄位。
本頁內容
MongoDB 文件可以包含嵌入式文件,例如使用者記錄中的 address 物件。投影會控制查詢傳回哪些欄位。例如,選取 address.city 會傳回該巢狀值,同時保留其巢狀結構。若要取得一般查詢結果,請使用 find() 投影;若要在聚合管道中調整文件形狀,請使用 $project;若要從管道結果中移除指定欄位,請使用 $unset。
了解 MongoDB 的巢狀欄位投影
假設文件有 name 和 address 欄位,而 address 包含 street、city 和 country。巢狀路徑使用點記法,例如 address.city。投影會改變傳回的文件,不會修改儲存的來源文件。以下範例都使用相同的文件結構。在 find() 投影中,除非明確排除,否則 _id 預設會包含在結果中。
使用點記法搭配 find() 選取巢狀欄位
若只想傳回巢狀 address 中的城市,請加入它的點記法路徑。以下 MongoDB shell 表達式僅用於說明語法,未在設定的執行環境中執行:
db.users.find({}, { "address.city": 1, "_id": 0 })
傳回的結構為 { "address": { "city": "New York" } }。如果希望每筆結果保留識別碼,請省略 _id: 0。若要排除巢狀路徑並保留其他欄位,請使用 0,例如 { "address.country": 0 }。
包含欄位的投影通常不能混用包含與排除欄位。_id 是特殊例外:包含其他路徑時,仍可排除 _id。其他欄位請擇一使用包含投影或排除投影。
執行此範例:
本節中的程式碼以及顯示的標籤或輸出仍為英文。
document = {"name": "Ava", "address": {"city": "New York", "country": "USA"}}
result = {"address": {"city": document["address"]["city"]}}
print(result)
{'address': {'city': 'New York'}}
這個簡短的 Python 範例用來說明傳回結果的巢狀結構;它不會連線至 MongoDB。上方的 MongoDB 查詢使用了對應的點記法路徑。
使用 $project 聚合階段調整巢狀欄位形狀
在聚合管道中,$project 可以包含巢狀路徑,也能將來源路徑對應到輸出欄位。例如,{ $project: { _id: 0, city: "$address.city", name: 1 } } 會將 city 傳回頂層,並與 name 一起呈現。直接包含路徑,例如 { $project: { "address.city": 1, _id: 0 } },則會保留 address.city 的巢狀結構。當管道需要特定輸出形狀時,$project 就很有用。表達式也能計算輸出值;請確認每個表達式參照的欄位都存在於輸入文件中。
使用 $unset 聚合階段排除巢狀欄位
使用聚合 $unset 階段可移除一個或多個路徑,同時保留其他欄位:{ $unset: ["address.country"] }。點記法路徑會從管道結果中移除該巢狀欄位。$unset 會改變哪些欄位繼續流經管道,但不會篩除文件。若要篩選文件,請改用查詢條件或 $match 階段。這是聚合功能,與使用相同名稱的更新運算子不同。
如何選擇查詢投影或聚合
若查詢只需在傳回的文件中包含或排除欄位,請搭配點記法使用 find()。若聚合需要重新命名路徑、計算值或明確定義輸出形狀,請選擇 $project。若管道應保留大部分欄位,只移除少數欄位,請選擇 $unset。$addFields 會新增或取代欄位,同時保留文件的其餘部分,因此不能用來取代投影選取。以上三種方式都只會影響結果或欄位形狀,不會修改儲存的文件。