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 (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 Change Streams 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 Change Streams (Luồng thay đổi) tương thích với MongoDB của Firestore có thể xử lý mọi công suất ghi và đọc thông qua một quy trình triển khai duy nhất về việc phân vùng tự động khi ghi và tính song song khi đọc. Điều này cho phép bạn tạo các 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 Change Streams song song. Điều này cho phép bạn tạo các tải đọ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 hợp lý.
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 tập hợp.
- Khoảng thời gian lưu giữ cho một luồng thay đổi được chỉ định tại thời điểm 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 khoảng 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.
delete,insert,updatevàdroplà các sự kiện thay đổi có thể quan sát được bằng cách sử dụngdb.collection.watch()vàdb.watch().updateDescription.updatedFieldschứa các khác biệt về bản cập nhật.- Tất cả các lựa chọn
fullDocumentvàfullDocumentBeforeChange.- Tìm kiếm toàn bộ tài liệu để biết thông tin cập nhật.
- Hình ảnh trước của tài liệu trước khi tài liệu đó đượ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ờ cần 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 lựa chọn tiếp tục, bao gồm cả
resumeAftervàstartAfter. - Khi dùng
watch()để theo dõi 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 các 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 đối tượng 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. Không được hỗ trợ 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.
Để 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 Google Cloud, hãy chuyển đến trang 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 Trình khám phá, hãy tìm nút Change streams (Luồng thay đổi), nhấp vào Tuỳ chọn khác, rồi chọn Tạo luồng thay đổi.
- Nhập tên, phạm vi và khoảng thời gian lưu giữ riêng biệt cho luồng thay đổi, rồi nhấp vào Lưu
Xem các sự kiện phát trực tiếp
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 Google Cloud, hãy chuyển đến trang 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 Bật/tắt 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 Google Cloud, hãy chuyển đến trang 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 Bật/tắt 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 Thao tác khác rồi chọn Xoá luồng thay đổi.
- Trong hộp thoại, hãy nhập tên của luồng thay đổi để xác nhận việc xoá, sau đó nhấp vào 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 tập hợ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 theo 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 một con trỏ có phạm vi là 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 tập hợp tương ứng.
let cursor = db.my_collection.watch()
Giờ đây, bạn có thể bắt đầu truyền phát trực tiếp sau khi tạo con trỏ luồng thay đổi.
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 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 một luồng thay đổi
Để tiếp tục một luồng thay đổi, hãy sử dụng các lựa chọn resumeAfter hoặc startAfter.
Để xác định vị trí trong nhật ký thay đổi cần 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})
Thêm hình ảnh trước và sau khi cập nhật và xoá
Nếu cần, bạn có thể thêm 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 này chỉ hoạt động trong khoảng thời gian khôi phục tại một thời điểm (PITR). Để đọc hình ảnh tài liệu cũ hơn một giờ, bạn phải bật PITR.
Change Streams tận dụng khoảng thời gian PITR để cung cấp chế độ xem tài liệu trước và sau sự kiện thay đổi nhất định. Theo mặc định, các sự kiện cập nhật chứa một trường updateDescription là mức chênh lệch của các trường do thao tác cập nhật sửa đổi.
Để đưa hình ảnh trước và sau vào một sự kiện thay đổi, bạn phải chỉ định các lựa 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 khoảng thời gian 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ủ.
Thay vì 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 một trường updateDescription là mức chênh lệch của các trường do thao tác cập nhật sửa đổi. Để tra cứu 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 lựa chọn fullDocument.
Tính năng này không yêu cầu PITR và thực hiện tra cứu tài liệu.
let cursor = db.my_collection.watch({ "fullDocument": "updateLookup", })
Đọc song song
Để tăng công suất, bạn có thể sử dụng lựa chọn firestoreWorkerConfig để chia một truy vấn luồng thay đổi trên nhiều worker. Mỗi worker chịu trách nhiệm phân phát các thay đổi cho một nhóm tài liệu riêng biệt. Bạn phải tạo một con trỏ song song thông qua truy vấn runCommand hoặc aggregate.
Ví dụ: bạn có thể phân phối một luồng thay đổi trên 3 worker 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 }} }]);
Thay đổi luồng 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 Change Streams, bạn phải tạo lại các luồng thay đổi đó trong cơ sở dữ liệu đích để mở con trỏ đến cơ sở dữ liệu đó.
Thanh toán
- Change Streams phát sinh chi phí về đơn vị đọc và bộ nhớ. Xem giá của luồng thay đổi.
- Để bao gồm hình ảnh trước và sau có thời gian hơn 1 giờ tại thời điểm yêu cầu đọc, bạn phải bật PITR. Việc này sẽ phát sinh chi phí PITR.
Điểm khác biệt về hành vi
Phần sau đây mô tả những điểm 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 thao tác cập nhật cập nhật hoặc xoá. 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.updatedFieldsbiểu thị sự khác biệt chính tắc giữa hình ảnh trước và sau của một tài liệu trước và sau khi áp dụng một đột biến.
Hãy xem xét 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}] } })
Tình huống 1: chỉ thay đổi phần tử đầu tiên của mảng.
Trong trường hợp này, hành vi Cloud Firestore 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.
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: [] }