MongoDB 檢視

最後更新: 2021-07-25 21:42:07 +0800 +0800
原文以英文撰寫。您正在閱讀AI翻譯版本。

MongoDB 檢視是建立在集合或另一個檢視上的唯讀查詢定義。檢視儲存的是聚合管線,而非管線結果,因此每次讀取都會將管線套用至目前的來源資料。標準檢視不提供具體化檢視快取。

建立檢視 #

db.createView() 接受目標集合名稱、來源命名空間與聚合管線:

javascript
db.createView(
  "active_orders",
  "orders",
  [
    { $match: { status: "active" } },
    { $project: { customerId: 1, total: 1, createdAt: 1 } }
  ]
)

用戶端查詢 active_orders 的方式與查詢集合相同:

javascript
db.active_orders.find({ customerId: customerId })

伺服器會將檢視定義與用戶端查詢組合,並針對來源集合規劃結果。標準檢視使用底層集合上的索引;一般用途索引不能直接在標準檢視上建立、刪除或重建。請提早放置具選擇性的 $match 階段,並為管線與用戶端查詢使用的來源欄位建立索引。

也可以使用 db.createCollection() 建立檢視:

javascript
db.createCollection("recent_orders", {
  viewOn: "orders",
  pipeline: [
    { $match: { createdAt: { $gte: ISODate("2026-01-01") } } }
  ],
  collation: { locale: "en", strength: 2 }
})

檢視與其來源必須位於相同資料庫。檢視的預設定序在建立時固定,查詢不能以不同定序覆寫它。

設計限制 #

檢視可以暴露欄位子集、重新命名欄位、使用 $lookup 連接另一個集合,或聚合資料。它不能接受插入、更新或刪除。包括 $out 與 $merge 在內的不支援聚合階段不能出現在標準檢視定義中,因為它們會寫入資料。

檢視可以依賴其他檢視,但相依圖不得包含迴圈。請保持管線具確定性並有界。每次請求都執行大型 $lookup、$group 或排序的管線,會將作業成本從寫入轉移到讀取。

檢視不支援時間點或快照讀取隔離。阻塞聚合階段也受伺服器聚合記憶體與暫存檔案行為限制。請說明並進行最終查詢的負載測試,不要假設將管線隱藏在檢視後就會變得便宜。

授權與綱要邊界 #

啟用驗證時,建立檢視需要其資料庫上的 createCollection 權限,以及對所參照命名空間的相關讀取權限。查詢檢視需要檢視命名空間上的 find 權限;用戶端不需要同時對來源集合擁有直接 find 權限。

授權分離可以暴露受控制的投影,例如不含個人識別欄位的員工記錄。若其他權限仍暴露來源集合、中繼資料或側通道,檢視就不是完整的安全邊界。請只授予應用程式帳戶所需的命名空間與命令。

標準檢視沒有獨立的文件驗證綱要,因為它不能接受寫入。來源集合上的驗證會限制對該集合的寫入,但不保證投影、$lookup 或計算欄位永遠符合應用程式綱要。請一併版本化檢視定義與取用者契約。檢視及其參照的每個命名空間都必須位於相同資料庫;檢視不能跨越資料庫命名空間邊界。

標準與按需具體化檢視 #

需要新鮮度且底層查詢便宜時,標準檢視很適合。衍生結果昂貴但可以容忍重新整理延遲時,MongoDB 將由聚合管線填入的集合稱為按需具體化檢視:

javascript
db.orders.aggregate([
  { $group: { _id: "$customerId", lifetimeValue: { $sum: "$total" } } },
  { $merge: { into: "customer_lifetime_value", whenMatched: "replace",
              whenNotMatched: "insert" } }
])

目標是實際集合,因此可以建立索引並有效查詢。$merge 可以遞增地取代相符文件,而 $out 會取代目標集合。排程器、變更串流取用者、Atlas Stream Processing 管線或應用程式工作流程必須重新整理結果。請明確陳述新鮮度契約,因為一般聚合不會持續維護按需具體化檢視。

當 $merge 作業更新許多文件時,讀取者可能觀察到部分重新整理的目標。若取用者需要單一版本可見性,請寫入版本化集合,驗證後切換小型中繼資料指標,再淘汰舊版本。作業程序中要納入重複儲存、索引建置、重新整理期間的變更擷取,以及清理失敗。

取用者需要透過變更串流監看目標時,請使用 $merge。透過 $out 取代的集合不能以相同的具體化檢視更新機制監看。

參考資料 #

評論

在 GitHub 上閱讀或評論(發表評論需要登入)