删除

delete() 是一个数据操纵语言 (DML) 阶段,允许查询根据查询结果移除文档。此阶段可附加到查询的末尾,并将删除上一个阶段的 __name__ 字段所引用的所有文档。

示例

例如,以下查询会删除所有 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();

行为

回答

delete() 阶段始终会发出一个文档(例如 { documents_modified: 28L }),用于描述删除了多少个文档。

完全删除合集

您可以通过将 delete() 附加到输入阶段来删除集合中的所有文档,如下所示:

Node.js

const results = await db.pipeline()
  .collection("/users")
  .delete()
  .execute();

确保最终 delete() 之前的 where(...) 阶段正确限制了文档,以便仅更新预期文档。建议先运行不含最终 delete() 阶段的查询,以验证是否仅移除了预期的文档。

最终阶段

delete() 阶段必须位于流水线的末尾,不得再提供其他阶段。

全部删除

默认情况下,delete() 阶段会移除上一个阶段引用的所有文档。如果您想限制工作负载的大小,或者知道过滤条件恰好匹配一个文档,则可以在最终的 delete() 之前添加 limit(1) 来限制总工作量。

跨集合突变

最终的 delete() 阶段会将更改应用于 __name__ 引用的任何文档(假设已提供所有必要的身份验证)。这包括在同一请求中删除多个不同集合或集合组中的文档。

需要__name__

delete() 阶段要求前一阶段提供一个 __name__ 字段,其中包含要移除的文档引用。否则,会导致运行时错误,并且在事务外部运行时可能会导致部分成功。

大多数输入阶段(例如 collection(...)collection_group(...)database(...)documents(...))默认包含 __name__ 字段,因此只有在使用投影(例如 select(...))或对文档执行转换(例如 aggregate(...))时,此字段才相关。

响应包含修改的文档数量的摘要。 例如,以下响应确认流水线修改了三个文档:

{documents_modified: 3L}

限制

  • DML 阶段不支持 Cloud Firestore Security Rules。通过 Cloud Firestore Security Rules 尝试执行 DML 操作会被拒绝。

  • 在预览版阶段,您无法在事务中运行 DML 阶段。如需详细了解一致性行为,请参阅一致性

  • 如果 DML 阶段之前的阶段生成了多个具有相同 __name__ 的文档,则每个实例都会被处理。对于 update(...),这意味着同一目标文档可能会被多次修改。对于 delete(...),第一次尝试之后的后续尝试将不会执行任何操作。