使用流水线操作修改数据

使用 update(...)delete(...) 数据操纵语言 (DML) 阶段来构建数据流水线,这些流水线可以查询文档,然后删除或修改数据。

版本要求

本页介绍的操作需要 Firestore 企业版。

准备工作

您应该熟悉如何 使用流水线操作查询数据库

更新文档

使用 update(...) DML 阶段来构建数据流水线 ,这些流水线可以查询文档,然后添加或修改数据。

所有 DML 阶段都必须位于流水线的末尾。 进入此阶段的文档必须包含 __name__ 字段,以标识要更新的文档。如果您尝试更新的任何文档不存在,该操作将失败。

例如,以下操作会将数据模型更改回填到合集组中的所有文档。流水线会将 preferences.color 字段添加到 users 合集组中缺少该字段的所有文档。

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();

删除文档

使用 delete(...) 阶段 DML 阶段来构建数据流水线 ,这些流水线可以查询文档,然后删除数据。 为防止意外批量删除,以 delete(...) 结尾的流水线应至少包含一个 where(...) 阶段。 所有 DML 阶段都必须位于流水线的末尾。

例如,以下流水线会删除所有 users 文档,这些文档的 address.users 设置为 USA,且 __create_time__ 小于 10 天:

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();

一致性

事务中不支持使用 update(...)delete() 阶段的流水线操作。DML 阶段在事务外部运行,具有以下行为:

  • 每个文档都会单独更新。这意味着操作在文档之间不是原子性的。 操作会在第一个错误时失败,并且可能会部分成功。
  • 支持以下阶段:
    • collection(...)
    • collection_group(...)
    • where(...)
    • select(...)
    • add_fields(...)
    • remove_fields(...)
    • let(...)
    • sort(...)
    • limit(...)
    • offset(...)
  • 不支持以下阶段:
    • aggregate(...)
    • distinct(...)
    • unnest(...)
    • find_nearest(...)
    • DML 阶段之前不允许使用多查询阶段,例如 union(...)、联接和子查询。

限制

请注意 DML 阶段的以下限制:

  • DML 阶段必须是调用 .execute() 之前的流水线定义中的最后一个阶段。
  • 事务中不支持使用 update(...)delete() 阶段的流水线操作。
  • 如果 DML 阶段之前的阶段生成了多个具有相同 __name__ 的文档,则系统会处理每个实例。对于 update(...),这意味着同一个目标文档可能会被多次修改。对于 delete(...),第一次尝试后的后续尝试将是空操作。