與 MongoDB 相容的 Firestore 變更串流,可讓應用程式存取集合或整個資料庫的即時變更 (插入、更新和刪除)。變更串流會依修改時間排序更新。
您可以透過與 MongoDB 相容的 API 和傳統 MongoDB 驅動程式存取變更串流。與 MongoDB 相容的 Firestore 實作變更串流時,會對寫入作業自動分區,並平行處理讀取作業,因此可處理任何讀寫作業的處理量。這可讓您建構高處理量的工作負載。您也可以改善 Cloud Firestore 與其他儲存空間解決方案之間的遷移和資料同步基礎架構。
除了與 MongoDB 驅動程式相容外,您還可以使用 Cloud Firestore 平行讀取變更串流。這可讓您建構平行、高處理量的讀取工作負載。每個串流都代表結果的分區,且分布良好。
變更串流支援下列功能:
- 可設定變更串流,範圍為資料庫或集合。
- 建立變更串流時指定的保留期限。預設保留期限為 7 天,最短為 1 天。保留期限必須是 1 天的倍數,最多 7 天。保留時間長度建立後即無法變更。如要變更保留期限,您必須捨棄並重新建立變更串流。
delete、insert、update和drop變更事件,可使用db.collection.watch()和db.watch()觀測。updateDescription.updatedFields包含更新差異。- 所有
fullDocument和fullDocumentBeforeChange選項。- 正在查詢完整文件,確認是否有更新。
- 文件在替換、更新或刪除前的預先映像檔。
- 文件替換或更新後的圖片。
- 如要使用一小時前的映像檔,必須啟用時間點復原 (PITR) 功能。
- 所有繼續選項,包括
resumeAfter和startAfter。 - 使用
watch()觀察變更時,您可以鏈結$addFields、$match、$project、$replaceRoot、$replaceWith、$set和$unset等匯總階段。
設定變更串流
如要建立、捨棄或查看資料庫的現有變更串流,請使用 Google Cloud 控制台。
角色和權限
如要建立、刪除及列出變更串流,主體必須分別具備 datastore.schemas.create、datastore.schemas.delete 和 datastore.schemas.list Identity and Access Management (IAM) 權限。
例如,Datastore 索引管理員 (roles/datastore.indexAdmin) 角色會授予這些權限。
建立變更串流
您必須先建立變更串流,才能開啟對應的變更串流游標。不支援在建立集合或資料庫時,自動啟用變更串流。
如要建立異動串流,請使用 Google Cloud 控制台。
-
前往 Google Cloud 控制台的「Databases」(資料庫) 頁面。
- 從清單中選取與 MongoDB 相容的 Firestore 資料庫。「Firestore Studio」面板隨即開啟。
- 在「Explorer」面板中,找到「變更串流」 節點,按一下 「More actions」(更多動作),然後選取「建立變更串流」。
- 輸入不重複的異動串流名稱、範圍和保留期限,然後按一下「Save」(儲存)
查看變更串流
您可以在 Google Cloud 控制台查看變更串流的詳細資料。
-
前往 Google Cloud 控制台的「Databases」(資料庫) 頁面。
- 從清單中選取與 MongoDB 相容的 Firestore 資料庫。「Firestore Studio」面板隨即開啟。
- 在「Explorer」面板中,找出「變更串流」 節點。
- 如要開啟或關閉節點,請按一下「 切換節點」。
刪除變更串流
如要刪除變更串流,請使用 Google Cloud 控制台。
-
前往 Google Cloud 控制台的「Databases」(資料庫) 頁面。
- 從清單中選取與 MongoDB 相容的 Firestore 資料庫。「Firestore Studio」面板隨即開啟。
- 在「Explorer」面板中,找出「變更串流」 節點。
- 如要開啟或關閉節點,請按一下「 切換節點」。
- 在「Explorer」中,找出要刪除的變更串流。
- 按一下「More actions」(更多動作) 圖示 ,然後選取「Delete change stream」(刪除變更串流)。
- 在對話方塊中輸入變更串流名稱,確認刪除,然後按一下「Delete」(刪除)。
開啟或繼續變更串流游標
以下範例說明如何建立、繼續及設定變更串流游標。
建立變更串流游標前,您必須明確為資料庫或集合建立變更串流。
建立變更串流游標
如要建立新的變更串流游標,請使用 MongoDB 驅動程式中的 watch 方法。如要監聽資料庫的所有變更,請建立資料庫範圍的變更串流,並對 db 物件呼叫 watch 方法。
let cursor = db.watch()
如要建立限定集合範圍的游標,必須先為該集合建立變更串流。接著,在對應的集合上呼叫 watch 方法。
let cursor = db.my_collection.watch()
建立變更串流游標後,即可開始串流。舉例來說,如果您插入文件並在游標上呼叫 tryNext,就會看到變更出現在變更串流中。
let doc = db.my_collection.insertOne({value: "hello world"}) console.log(cursor.tryNext())
如果您更新及刪除文件,則會看到這些變更顯示在變更串流中:
db.my_collection.updateOne({"_id": doc.insertedId}, {$set: {value: "hello world!"}}) db.my_collection.deleteOne({"_id": doc.insertedId}}) // Prints the update event console.log(cursor.tryNext()) // Prints the delete event console.log(cursor.tryNext())
繼續變更串流
如要繼續執行變更串流,請使用 resumeAfter 或 startAfter 選項。如要判斷從 resumeAfter 和 startAfter 繼續執行變更記錄的位置,請使用繼續權杖。
// Create a cursor and add one event to the change stream. let cursor = db.my_collection.watch(); db.my_collection.insertOne({value: "hello world"}); let event = cursor.tryNext(); // Get the resume token from the event. let resumeToken = event._id; // Add a new event to the change stream. db.my_collection.insertOne({value: "foobar"}); // Create a new cursor by using the resume token as a starting point. let newCursor = db.my_collection.watch({resumeAfter: resumeToken}) // Log the change event containing the "foobar" value. console.log(newCursor.tryNext())
如何使用 startAfter:
// Start after the resume token. let startAfterCursor = db.my_collection.watch({startAfter: resumeToken})
在更新和刪除作業中加入前後映像檔
如有需要,您可以在更新和刪除變更事件中,加入文件的前後圖片。映像檔可用性取決於時間點復原 (PITR) 期間,如要讀取超過一小時的文件映像檔,必須啟用 PITR。
變更串流會利用 PITR 期間,提供指定變更事件前後的文件檢視畫面。根據預設,更新事件包含 updateDescription 欄位,也就是更新作業修改的欄位差異。
如要在變更事件中加入前後圖片,您必須在變更串流查詢中指定 fullDocumentBeforeChange 和 fullDocument 選項。
let cursor = db.my_collection.watch({ "fullDocument": "required", "fullDocumentBeforeChange": "required" })
如果查詢嘗試讀取 PITR 保留時間範圍以外的文件,或未啟用 PITR,則 required 值會擲回伺服器端錯誤訊息。
除了擲回錯誤,您也可以使用 whenAvailable 值,在圖片不再可用時傳回 null 值。
let cursor = db.my_collection.watch({ "fullDocument": "whenAvailable", "fullDocumentBeforeChange": "whenAvailable" })
在更新中加入目前的圖片
根據預設,更新事件包含 updateDescription 欄位,也就是更新作業修改的欄位差異。如要改為查詢整份文件的最新版本,請在 fullDocument 選項中使用 updateLookup 值。
這項功能不需要 PITR,且會執行文件查詢。
let cursor = db.my_collection.watch({ "fullDocument": "updateLookup", })
平行讀取
如要提高處理量,可以使用 firestoreWorkerConfig 選項,將變更串流查詢分散至多個 worker。每個 worker 負責提供一組不同文件的變更。您必須透過 runCommand 或 aggregate 查詢建立平行游標。
舉例來說,您可以將變更串流分配給 3 個 worker,如下所示:
let cursor1 = db.my_collection.aggregate([{ "$changeStream": { "firestoreWorkerConfig": {numWorkers: 3, workerId: 0 }} }]); let cursor2 = db.my_collection.aggregate([{ "$changeStream": { "firestoreWorkerConfig": {numWorkers: 3, workerId: 1 }} }]); let cursor3 = db.my_collection.aggregate([{ "$changeStream": { "firestoreWorkerConfig": {numWorkers: 3, workerId: 2 }} }]);
變更串流和備份
備份還原作業不提供變更串流設定和變更串流資料。如果還原的資料庫含有變更串流,您必須在目的地資料庫中重新建立這些變更串流,才能開啟該資料庫的游標。
帳單
- 變更串流會產生讀取單位和儲存空間費用。請參閱變更串流定價。
- 如要納入讀取要求時間超過 1 小時的前後映像檔,您必須啟用 PITR,這會產生 PITR 費用。
行為差異
以下各節說明與 MongoDB 相容的 Firestore 和 MongoDB 之間的變更串流差異。
updateDescription
updateDescription 是 update 事件中的文件,說明更新作業更新或移除的欄位。在 Cloud Firestore 中,主要差異如下:
- 在
updateDescription中,系統不會填入truncatedArrays和disambiguatedPaths欄位。 updateDescription.updatedFields代表套用異動前後,文件圖片的標準差異。
假設文件的初始狀態如下:
db.my_collection.insertOne({ _id: 1, root: { array: [{a: 1}, {b: 2}, {c: 3}] } })
情境 1:只變動陣列的第一個元素。
在這種情況下,Cloud Firestore 的行為與 MongoDB 一致。
db.my_collection.updateOne( {_id: 1}, {'$set': {"root.array.0.a": 100}} ) { updatedFields: {"root.array.0.a": 100}, removedFields: [] }
情境 2:以整個陣列覆寫
在這種情況下,作業只會更新第一個陣列欄位,但會覆寫整個陣列。
Cloud Firestore 更新差異不會區分這兩種情況,並會為兩者傳回相同的 updateDescription.updatedFields:
db.my_collection.updateOne( {_id: 1}, {'$set': {"root.array": [{a: 100}, {b: 2}, {c: 3}]}} ) // In other implementations, updatedFields reflects the mutation itself { updatedFields: { "root.array": [{a: 100}, {b: 2}, {c: 3}] }, removedFields: [] } // Firestore updatedFields is the diff between the before and after versions of the document { updatedFields: {"root.array.0.a": 100}, removedFields: [] }