Luồng thay đổi cho Firestore có khả năng tương thích với MongoDB cho phép các ứng dụng truy cập vào các thay đổi theo thời gian thực (thao tác chèn, cập nhật và xoá) được thực hiện đối với một bộ sưu tập hoặc toàn bộ cơ sở dữ liệu. Luồng thay đổi sắp xếp các bản cập nhật theo thời gian sửa đổi.
Bạn có thể truy cập vào Luồng thay đổi thông qua các API tương thích với MongoDB và Trình điều khiển MongoDB truyền thống. Việc triển khai Luồng thay đổi của Firestore có khả năng tương thích với MongoDB có thể xử lý mọi công suất ghi và đọc thông qua một cách triển khai duy nhất về việc phân vùng tự động trên các thao tác ghi và tính song song khi đọc. Điều này cho phép bạn xây dựng khối lượng công việc có thông lượng cao. Bạn cũng có thể cải thiện cơ sở hạ tầng di chuyển và đồng bộ hoá dữ liệu giữa Cloud Firestore và các giải pháp lưu trữ khác.
Ngoài khả năng tương thích với trình điều khiển MongoDB, bạn có thể sử dụng Cloud Firestore để đọc Luồng thay đổi song song. Điều này cho phép bạn xây dựng khối lượng công việc đọc song song có thông lượng cao. Mỗi luồng đại diện cho một phân vùng kết quả được phân phối tốt.
Luồng thay đổi hỗ trợ các tính năng sau:
- Luồng thay đổi có thể định cấu hình với phạm vi cơ sở dữ liệu hoặc bộ sưu tập.
- Thời gian lưu giữ cho một luồng thay đổi được chỉ định khi tạo. Thời gian lưu giữ mặc định là 7 ngày và thời gian lưu giữ tối thiểu là 1 ngày. Thời gian lưu giữ phải là bội số của 1 ngày, tối đa là 7 ngày. Bạn không thể thay đổi thời gian lưu giữ sau khi tạo. Để thay đổi khoảng thời gian lưu giữ, bạn phải xoá và tạo lại luồng thay đổi.
- Các sự kiện thay đổi
delete,insert,updatevàdropcó thể quan sát được bằng cách sử dụngdb.collection.watch()vàdb.watch(). updateDescription.updatedFieldschứa các điểm khác biệt về bản cập nhật.- Tất cả các tuỳ chọn
fullDocumentvàfullDocumentBeforeChange.- Tìm tài liệu đầy đủ để cập nhật.
- Hình ảnh trước của tài liệu trước khi được thay thế, cập nhật hoặc xoá.
- Hình ảnh sau của tài liệu sau khi được thay thế hoặc cập nhật.
- Hình ảnh trước và sau có thời gian hơn một giờ yêu cầu phải bật tính năng khôi phục tại một thời điểm (PITR).
- Tất cả các tuỳ chọn tiếp tục, bao gồm
resumeAftervàstartAfter. - Khi sử dụng
watch()để quan sát các thay đổi, bạn có thể liên kết các giai đoạn tổng hợp như$addFields,$match,$project,$replaceRoot,$replaceWith,$setvà$unset.
Định cấu hình Luồng thay đổi
Để tạo, xoá hoặc xem Luồng thay đổi hiện có cho một cơ sở dữ liệu, hãy sử dụng bảng điều khiển Cloud của Google.
Vai trò và quyền
Để tạo, xoá và liệt kê Luồng thay đổi, một thực thể chính cần có các quyền Quản lý danh tính và quyền truy cập (IAM) datastore.schemas.create, datastore.schemas.delete và datastore.schemas.list tương ứng.
Ví dụ: vai trò Quản trị viên chỉ mục Datastore (roles/datastore.indexAdmin) cấp các quyền này.
Tạo luồng thay đổi
Trước khi có thể mở con trỏ luồng thay đổi tương ứng, bạn phải tạo một luồng thay đổi. Tính năng tự động bật luồng thay đổi khi tạo bộ sưu tập hoặc cơ sở dữ liệu không được hỗ trợ.
Để tạo một luồng thay đổi, hãy sử dụng bảng điều khiển Cloud.
-
Trong bảng điều khiển Cloud, hãy chuyển đến trang Databases (Cơ sở dữ liệu).
- Trong danh sách, hãy chọn một cơ sở dữ liệu Firestore có khả năng tương thích với MongoDB. Bảng điều khiển Firestore Studio sẽ mở ra.
- Trong bảng điều khiển Explorer (Trình khám phá), hãy tìm nút Change streams (Luồng thay đổi), nhấp vào biểu tượng More actions (Thao tác khác), sau đó chọn Create change stream (Tạo luồng thay đổi).
- Nhập tên luồng thay đổi, phạm vi và khoảng thời gian lưu giữ riêng biệt, sau đó nhấp vào Save (Lưu)
Xem Luồng thay đổi
Bạn có thể xem thông tin chi tiết về Luồng thay đổi trong bảng điều khiển Cloud.
-
Trong bảng điều khiển Cloud, hãy chuyển đến trang Databases (Cơ sở dữ liệu).
- Trong danh sách, hãy chọn một cơ sở dữ liệu Firestore có khả năng tương thích với MongoDB. Bảng điều khiển Firestore Studio sẽ mở ra.
- Trong bảng điều khiển Explorer (Trình khám phá), hãy tìm nút Change streams (Luồng thay đổi).
- Để mở hoặc đóng nút, hãy nhấp vào Toggle node (Chuyển đổi nút).
Xoá luồng thay đổi
Để xoá một luồng thay đổi, hãy sử dụng bảng điều khiển Cloud.
-
Trong bảng điều khiển Cloud, hãy chuyển đến trang Databases (Cơ sở dữ liệu).
- Trong danh sách, hãy chọn một cơ sở dữ liệu Firestore có khả năng tương thích với MongoDB. Bảng điều khiển Firestore Studio sẽ mở ra.
- Trong bảng điều khiển Explorer (Trình khám phá), hãy tìm nút Change streams (Luồng thay đổi).
- Để mở hoặc đóng nút, hãy nhấp vào Toggle node (Chuyển đổi nút).
- Trong Explorer (Trình khám phá), hãy tìm luồng thay đổi mà bạn muốn xoá.
- Nhấp vào biểu tượng More actions (Thao tác khác) và sau đó chọn Delete change stream (Xoá luồng thay đổi).
- Trong hộp thoại, hãy nhập tên luồng thay đổi để xác nhận việc xoá, sau đó nhấp vào Delete (Xoá).
Mở hoặc tiếp tục con trỏ luồng thay đổi
Các ví dụ sau đây minh hoạ cách tạo, tiếp tục và định cấu hình con trỏ luồng thay đổi.
Trước khi tạo con trỏ luồng thay đổi, bạn phải tạo một luồng thay đổi một cách rõ ràng cho cơ sở dữ liệu hoặc bộ sưu tập.
Tạo con trỏ luồng thay đổi
Để tạo con trỏ luồng thay đổi mới, hãy sử dụng phương thức watch trong trình điều khiển MongoDB.
Để theo dõi tất cả các thay đổi trên một cơ sở dữ liệu, hãy tạo một luồng thay đổi có phạm vi cơ sở dữ liệu và gọi phương thức watch trên đối tượng db.
let cursor = db.watch()
Để tạo con trỏ có phạm vi cho một bộ sưu tập, trước tiên, bạn phải tạo một luồng thay đổi cho bộ sưu tập đó. Sau đó, hãy gọi phương thức watch trên bộ sưu tập tương ứng.
let cursor = db.my_collection.watch()
Giờ đây, bạn đã tạo con trỏ luồng thay đổi, bạn có thể bắt đầu phát trực tuyến.
Ví dụ: nếu bạn chèn một tài liệu và gọi tryNext trên con trỏ, bạn sẽ thấy thay đổi xuất hiện trên luồng thay đổi.
let doc = db.my_collection.insertOne({value: "hello world"}) console.log(cursor.tryNext())
Nếu bạn cập nhật và xoá tài liệu, thì bạn sẽ thấy những thay đổi đó xuất hiện trên luồng thay đổi:
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())
Tiếp tục luồng thay đổi
Để tiếp tục luồng thay đổi, hãy sử dụng các tuỳ chọn resumeAfter hoặc startAfter.
Để xác định vị trí trong nhật ký thay đổi để tiếp tục từ resumeAfter và startAfter, hãy sử dụng mã thông báo tiếp tục.
// 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())
Cách sử dụng startAfter:
// Start after the resume token. let startAfterCursor = db.my_collection.watch({startAfter: resumeToken})
Đưa hình ảnh trước và sau vào bản cập nhật và xoá
Nếu cần, bạn có thể đưa hình ảnh trước và sau của tài liệu vào các sự kiện thay đổi khi cập nhật và xoá. Tính năng cung cấp hình ảnh tuân theo cửa sổ khôi phục tại một thời điểm (PITR), vàđể đọc hình ảnh tài liệu có thời gian hơn một giờ, bạn phải bậtPITR.
Luồng thay đổi tận dụng cửa sổ PITR để cung cấp chế độ xem tài liệu trước và sau sự kiện thay đổi đã cho. Theo mặc định, các sự kiện cập nhật chứa trường updateDescription là mức chênh lệch của các trường được sửa đổi bởi thao tác cập nhật.
Để đưa hình ảnh trước và sau vào sự kiện thay đổi,
bạn phải
chỉ định các tuỳ chọn fullDocumentBeforeChange và fullDocument trong truy vấn luồng thay đổi.
let cursor = db.my_collection.watch({ "fullDocument": "required", "fullDocumentBeforeChange": "required" })
Nếu truy vấn cố gắng đọc một tài liệu bên ngoài cửa sổ lưu giữ PITR hoặc nếu PITR không được bật, thì giá trị required sẽ gửi thông báo lỗi phía máy chủ.
Ngoài việc gửi lỗi, bạn có thể sử dụng giá trị whenAvailable để trả về giá trị null nếu hình ảnh không còn nữa.
let cursor = db.my_collection.watch({ "fullDocument": "whenAvailable", "fullDocumentBeforeChange": "whenAvailable" })
Đưa hình ảnh hiện tại vào bản cập nhật
Theo mặc định, các sự kiện cập nhật chứa trường updateDescription là mức chênh lệch của các trường được sửa đổi bởi thao tác cập nhật. Để thay vào đó, tìm phiên bản mới nhất của toàn bộ tài liệu, hãy sử dụng giá trị updateLookup trong tuỳ chọn fullDocument.
Tính năng này không yêu cầu PITR và thực hiện tìm kiếm tài liệu.
let cursor = db.my_collection.watch({ "fullDocument": "updateLookup", })
Đọc song song
Để tăng thông lượng, bạn có thể sử dụng tuỳ chọn firestoreWorkerConfig để chia truy vấn luồng thay đổi trên nhiều trình thực thi. Mỗi trình thực thi chịu trách nhiệm phân phát các thay đổi cho một tập hợp tài liệu riêng biệt. Bạn phải tạo con trỏ song song thông qua truy vấn runCommand hoặc aggregate.
Ví dụ: bạn có thể phân phối luồng thay đổi trên 3 trình thực thi như sau:
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 }} }]);
Luồng thay đổi và bản sao lưu
Cả cấu hình luồng thay đổi và dữ liệu luồng thay đổi đều không có trong các thao tác khôi phục bản sao lưu. Nếu khôi phục cơ sở dữ liệu bằng Luồng thay đổi, bạn phải tạo lại các luồng thay đổi đó trong cơ sở dữ liệu đích để mở con trỏ cho cơ sở dữ liệu đó.
Thanh toán
- Luồng thay đổi phát sinh các đơn vị đọc và chi phí lưu trữ. Xem giá luồng thay đổi.
- Để bao gồm hình ảnh trước và sau cũ hơn 1 giờ tại thời điểm yêu cầu đọc, bạn phải bật PITR. Điều này sẽ phát sinh chi phí PITR.
Sự khác biệt về hành vi
Phần sau đây mô tả sự khác biệt về Luồng thay đổi giữa Firestore có khả năng tương thích với MongoDB và MongoDB.
updateDescription
updateDescription là một tài liệu trong sự kiện update mô tả các trường
đã được cập nhật hoặc xoá bởi thao tác cập nhật. Trong
Cloud Firestore, những điểm khác biệt đáng chú ý là:
- Trong
updateDescription, các trườngtruncatedArraysvàdisambiguatedPathskhông được điền sẵn. updateDescription.updatedFieldsđại diện cho mức chênh lệch chính tắc giữa hình ảnh trước và sau của tài liệu trước và sau khi áp dụng thao tác đột biến.
Hãy cân nhắc trạng thái ban đầu sau đây của một tài liệu:
db.my_collection.insertOne({ _id: 1, root: { array: [{a: 1}, {b: 2}, {c: 3}] } })
Trường hợp 1: chỉ đột biến phần tử đầu tiên của mảng.
Trong trường hợp này, Cloud Firestore hành vi khớp với MongoDB.
db.my_collection.updateOne( {_id: 1}, {'$set': {"root.array.0.a": 100}} ) { updatedFields: {"root.array.0.a": 100}, removedFields: [] }
Trường hợp 2: ghi đè bằng toàn bộ mảng
Trong trường hợp này, thao tác chỉ cập nhật trường mảng đầu tiên nhưng ghi đè toàn bộ mảng.
Mức chênh lệch bản cập nhật Cloud Firestore không phân biệt giữa hai trường hợp này
và trả về cùng một updateDescription.updatedFields cho cả hai trường hợp:
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: [] }