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(...),第一次尝试后的后续尝试将是空操作。