Sửa đổi dữ liệu bằng các thao tác trong quy trình Firestore

Sử dụng các giai đoạn Ngôn ngữ thao tác dữ liệu (DML) update(...)delete(...) để tạo các quy trình dữ liệu có thể truy vấn tài liệu, sau đó xoá hoặc sửa đổi dữ liệu.

Yêu cầu đối với phiên bản

Các thao tác được mô tả trên trang này yêu cầu phiên bản Firestore Enterprise.

Trước khi bắt đầu

Bạn nên nắm rõ cách truy vấn cơ sở dữ liệu bằng các thao tác trong Pipeline.

Cập nhật tài liệu

Sử dụng giai đoạn DML update(...) để tạo các quy trình dữ liệu có thể truy vấn tài liệu, sau đó thêm hoặc sửa đổi dữ liệu.

Tất cả các giai đoạn DML phải nằm ở cuối quy trình. Các tài liệu đến giai đoạn này phải có trường __name__ để xác định tài liệu cần cập nhật. Thao tác sẽ không thành công nếu bất kỳ tài liệu nào bạn cố gắng cập nhật không tồn tại.

Ví dụ: thao tác sau đây sẽ bổ sung dữ liệu cũ một thay đổi về mô hình dữ liệu cho tất cả các tài liệu trong một nhóm bộ sưu tập. Quy trình này sẽ thêm trường preferences.color vào tất cả tài liệu trong nhóm bộ sưu tập users bị thiếu trường đó.

Node.js
const snapshot = await db.pipeline()
   .collectionGroup("users")
   .where(not(exists(field("preferences.color"))))
   .addFields(constant(null).as("preferences.color"))
   .removeFields("color")
   .update()
   .execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import Constant, Field, Not

snapshot = (
    client.pipeline()
    .collection_group("users")
    .where(Not(Field.of("preferences.color").exists()))
    .add_fields(Constant.of(None).as_("preferences.color"))
    .remove_fields("color")
    .update()
    .execute()
)
Java
Pipeline.Snapshot snapshot = firestore.pipeline()
   .collectionGroup("users")
   .where(not(exists(field("preferences.color"))))
   .addFields(constant((String) null).as("preferences.color"))
   .removeFields("color")
   .update()
   .execute().get();

Xoá tài liệu

Sử dụng các giai đoạn DML delete(...)giai đoạn để tạo các quy trình dữ liệu có thể truy vấn tài liệu rồi xoá dữ liệu. Để tránh xoá nhầm hàng loạt, các quy trình kết thúc bằng delete(...) phải có ít nhất một giai đoạn where(...). Tất cả các giai đoạn DML phải nằm ở cuối quy trình.

Ví dụ: quy trình sau đây sẽ xoá tất cả các tài liệu usersaddress.users được đặt thành USA và có __create_time__ dưới 10 ngày:

Node.js
const pipeline = db.pipeline()
  .collectionGroup("users")
  .where(field("address.country").equal("USA"))
  .where(field("__create_time__").timestampAdd("day", 10).lessThan(currentTimestamp()))
  .delete();
await pipeline.execute();
Python
from google.cloud.firestore_v1.pipeline_expressions import CurrentTimestamp, Field

snapshot = (
    client.pipeline()
    .collection_group("users")
    .where(Field.of("address.country").equal("USA"))
    .where(
        Field.of("__create_time__")
        .timestamp_add("day", 10)
        .less_than(CurrentTimestamp())
    )
    .delete()
    .execute()
)
Java
Pipeline.Snapshot deleteResults = firestore.pipeline()
  .collectionGroup("users")
  .where(field("address.country").equal("USA"))
  .where(field("__create_time__").add(constant(10)).lessThan(currentTimestamp()))
  .delete()
  .execute().get();

Tính nhất quán

Các thao tác trong quy trình có giai đoạn update(...)delete() không được hỗ trợ trong một giao dịch. Các giai đoạn DML chạy bên ngoài một giao dịch với hành vi sau:

  • Mỗi tài liệu được cập nhật độc lập. Điều này có nghĩa là các thao tác không phải là nguyên tử trên các tài liệu. Thao tác không thành công khi gặp lỗi đầu tiên và có thể thành công một phần.
  • Các giai đoạn sau đây được hỗ trợ:
    • collection(...)
    • collection_group(...)
    • where(...)
    • select(...)
    • add_fields(...)
    • remove_fields(...)
    • let(...)
    • sort(...)
    • limit(...)
    • offset(...)
  • Các giai đoạn sau đây không được hỗ trợ:
    • aggregate(...)
    • distinct(...)
    • unnest(...)
    • find_nearest(...)
    • Các giai đoạn có nhiều truy vấn như union(...), các thao tác kết hợp và truy vấn phụ không được phép xuất hiện trước giai đoạn DML.

Hạn chế

Hãy lưu ý các giới hạn sau đối với giai đoạn DML:

  • Các giai đoạn DML phải là các giai đoạn cuối cùng trong định nghĩa quy trình trước khi gọi .execute().
  • Các thao tác trong quy trình có giai đoạn update(...)delete() không được hỗ trợ trong một giao dịch.
  • Nếu giai đoạn trước giai đoạn DML tạo ra nhiều tài liệu có cùng __name__, thì mỗi phiên bản sẽ được xử lý. Đối với update(...), điều này có nghĩa là cùng một tài liệu đích có thể được sửa đổi nhiều lần. Đối với delete(...), các lần thử tiếp theo sau lần đầu tiên sẽ không hoạt động.