删除文档 #

一、Delete概述 #

1.1 基本语法 #

javascript
Delete(ref)

1.2 Delete特点 #

text
Delete特点:
├── 立即删除文档
├── 返回被删除的文档
├── 不可恢复(除非有备份)
├── 历史记录保留(根据history_days)
└── 需要适当权限

二、基本删除 #

2.1 通过Ref删除 #

javascript
// 删除单个文档
Delete(Ref(Collection("users"), "123456"))

// 返回被删除的文档
{
  ref: Ref(Collection("users"), "123456"),
  ts: 1704067200000000,
  data: {
    name: "Tom",
    email: "tom@example.com"
  }
}

2.2 通过索引删除 #

javascript
// 通过索引查找后删除
Let(
  {
    doc: Get(Match(Index("users_by_email"), "tom@example.com"))
  },
  Delete(Select(["ref"], Var("doc")))
)

2.3 删除返回值 #

javascript
// Delete返回被删除的文档
Let(
  {
    deleted: Delete(Ref(Collection("users"), "123456"))
  },
  {
    message: "User deleted",
    deletedId: Select(["ref", "id"], Var("deleted")),
    deletedName: Select(["data", "name"], Var("deleted"))
  }
)

三、条件删除 #

3.1 检查存在后删除 #

javascript
// 检查文档存在后删除
Let(
  {
    ref: Ref(Collection("users"), "123456")
  },
  If(
    Exists(Var("ref")),
    Delete(Var("ref")),
    { message: "Document not found" }
  )
)

3.2 状态验证删除 #

javascript
// 验证状态后删除
Let(
  {
    ref: Ref(Collection("orders"), "order_001"),
    doc: Get(Var("ref")),
    status: Select(["data", "status"], Var("doc"))
  },
  If(
    Or(
      Equals(Var("status"), "cancelled"),
      Equals(Var("status"), "completed")
    ),
    Delete(Var("ref")),
    Abort("Cannot delete order in current status")
  )
)

3.3 权限验证删除 #

javascript
// 验证所有者后删除
Let(
  {
    ref: Ref(Collection("posts"), "post_001"),
    doc: Get(Var("ref")),
    owner: Select(["data", "authorId"], Var("doc")),
    currentUser: CurrentIdentity()
  },
  If(
    Equals(Var("owner"), Var("currentUser")),
    Delete(Var("ref")),
    Abort("You don't have permission to delete this post")
  )
)

四、批量删除 #

4.1 Map批量删除 #

javascript
// 批量删除多个文档
Map(
  [
    Ref(Collection("users"), "1"),
    Ref(Collection("users"), "2"),
    Ref(Collection("users"), "3")
  ],
  Lambda("ref", Delete(Var("ref")))
)

4.2 Foreach批量删除 #

javascript
// 使用Foreach批量删除
Foreach(
  Paginate(Match(Index("users_by_status"), "deleted")),
  Lambda("ref", Delete(Var("ref")))
)

4.3 条件批量删除 #

javascript
// 条件批量删除
Foreach(
  Filter(
    Paginate(Documents(Collection("logs"))),
    Lambda("ref",
      Let(
        { doc: Get(Var("ref")) },
        LT(
          Select(["data", "createdAt"], Var("doc")),
          TimeSubtract(Now(), 30, "day")
        )
      )
    )
  ),
  Lambda("ref", Delete(Var("ref")))
)

4.4 分页批量删除 #

javascript
// 分页批量删除(处理大量数据)
Let(
  {
    deleteBatch: Query(
      Lambda("cursor",
        Let(
          {
            page: If(
              Equals(Var("cursor"), null),
              Paginate(Match(Index("old_logs")), { size: 100 }),
              Paginate(Match(Index("old_logs")), {
                size: 100,
                after: Var("cursor")
              })
            )
          },
          Do(
            Foreach(
              Select(["data"], Var("page")),
              Lambda("ref", Delete(Var("ref")))
            ),
            If(
              ContainsPath(Var("page"), ["after"]),
            Select(["after"], Var("page")),
              false
            )
          )
        )
      )
    )
  },
  Var("deleteBatch")
)

五、级联删除 #

5.1 手动级联删除 #

javascript
// 删除用户及其相关数据
Let(
  {
    userRef: Ref(Collection("users"), "user_001")
  },
  Do(
    // 删除用户的订单
    Foreach(
      Paginate(Match(Index("orders_by_user"), Var("userRef"))),
      Lambda("orderRef", Delete(Var("orderRef")))
    ),
    // 删除用户的评论
    Foreach(
      Paginate(Match(Index("comments_by_user"), Var("userRef"))),
      Lambda("commentRef", Delete(Var("commentRef")))
    ),
    // 删除用户
    Delete(Var("userRef"))
  )
)

5.2 复杂级联删除 #

javascript
// 删除订单及其订单项
Let(
  {
    orderRef: Ref(Collection("orders"), "order_001")
  },
  Do(
    // 删除订单项
    Foreach(
      Paginate(Match(Index("order_items_by_order"), Var("orderRef"))),
      Lambda("itemRef", Delete(Var("itemRef")))
    ),
    // 删除支付记录
    Foreach(
      Paginate(Match(Index("payments_by_order"), Var("orderRef"))),
      Lambda("paymentRef", Delete(Var("paymentRef")))
    ),
    // 删除订单历史
    Foreach(
      Paginate(Match(Index("order_history_by_order"), Var("orderRef"))),
      Lambda("historyRef", Delete(Var("historyRef")))
    ),
    // 删除订单
    Delete(Var("orderRef"))
  )
)

5.3 使用函数封装级联删除 #

javascript
// 创建级联删除函数
CreateFunction({
  name: "delete_user_cascade",
  role: Role("admin"),
  body: Query(
    Lambda("userRef",
      Do(
        // 删除所有关联数据
        Foreach(
          Paginate(Match(Index("orders_by_user"), Var("userRef"))),
          Lambda("ref", Delete(Var("ref")))
        ),
        Foreach(
          Paginate(Match(Index("posts_by_author"), Var("userRef"))),
          Lambda("ref", Delete(Var("ref")))
        ),
        Foreach(
          Paginate(Match(Index("comments_by_user"), Var("userRef"))),
          Lambda("ref", Delete(Var("ref")))
        ),
        // 最后删除用户
        Delete(Var("userRef"))
      )
    )
  )
})

// 使用函数
Call(Function("delete_user_cascade"), Ref(Collection("users"), "user_001"))

六、软删除 #

6.1 软删除实现 #

javascript
// 软删除:标记为已删除
Update(Ref(Collection("users"), "user_001"), {
  data: {
    deleted: true,
    deletedAt: Now()
  }
})

// 查询时过滤已删除
Filter(
  Paginate(Documents(Collection("users"))),
  Lambda("ref",
    Not(Select(["data", "deleted"], Get(Var("ref")), false))
  )
)

6.2 软删除索引 #

javascript
// 创建软删除索引
CreateIndex({
  name: "active_users",
  source: {
    collection: Collection("users"),
    fields: {
      notDeleted: Query(
        Lambda("doc",
          Not(Select(["data", "deleted"], Var("doc"), false))
        )
      )
    }
  },
  terms: [
    { binding: "notDeleted" }
  ]
})

// 查询活跃用户
Paginate(Match(Index("active_users"), true))

6.3 恢复软删除 #

javascript
// 恢复软删除的文档
Update(Ref(Collection("users"), "user_001"), {
  data: {
    deleted: false,
    deletedAt: null,
    restoredAt: Now()
  }
})

七、删除前备份 #

7.1 删除前复制 #

javascript
// 删除前复制到归档集合
Let(
  {
    ref: Ref(Collection("users"), "user_001"),
    doc: Get(Var("ref"))
  },
  Do(
    // 复制到归档
    Create(Collection("users_archive"), {
      data: Merge(
        Select(["data"], Var("doc")),
        {
          originalId: Select(["ref", "id"], Var("doc")),
          archivedAt: Now()
        }
      )
    }),
    // 删除原文档
    Delete(Var("ref"))
  )
)

7.2 批量归档删除 #

javascript
// 批量归档后删除
Foreach(
  Paginate(Match(Index("users_to_archive"))),
  Lambda("ref",
    Let(
      { doc: Get(Var("ref")) },
      Do(
        Create(Collection("users_archive"), {
          data: Merge(
            Select(["data"], Var("doc")),
            {
              originalId: Select(["ref", "id"], Var("doc")),
              archivedAt: Now()
            }
          )
        }),
        Delete(Var("ref"))
      )
    )
  )
)

八、删除验证 #

8.1 引用检查 #

javascript
// 检查是否有引用
Let(
  {
    productRef: Ref(Collection("products"), "prod_001"),
    orders: Match(Index("orders_by_product"), Var("productRef"))
  },
  If(
    Equals(Count(Var("orders")), 0),
    Delete(Var("productRef")),
    Abort("Cannot delete: product has orders")
  )
)

8.2 业务规则验证 #

javascript
// 复杂业务规则验证
Let(
  {
    orderRef: Ref(Collection("orders"), "order_001"),
    doc: Get(Var("orderRef"))
  },
  If(
    And(
      // 订单已完成或已取消
      Or(
        Equals(Select(["data", "status"], Var("doc")), "completed"),
        Equals(Select(["data", "status"], Var("doc")), "cancelled")
      ),
      // 订单创建超过30天
      GT(
        TimeDiff(Select(["data", "createdAt"], Var("doc")), Now(), "day"),
        30
      )
    ),
    Delete(Var("orderRef")),
    Abort("Cannot delete order: must be completed/cancelled and older than 30 days")
  )
)

九、实际应用示例 #

9.1 删除用户 #

javascript
// 完整的用户删除流程
Let(
  {
    userRef: Ref(Collection("users"), "user_001"),
    currentUser: CurrentIdentity()
  },
  If(
    Equals(Var("userRef"), Var("currentUser")),
    Abort("Cannot delete your own account"),
    Let(
      { doc: Get(Var("userRef")) },
      Do(
        // 归档用户数据
        Create(Collection("deleted_users"), {
          data: {
            originalId: Select(["ref", "id"], Var("doc")),
            email: Select(["data", "email"], Var("doc")),
            name: Select(["data", "name"], Var("doc")),
            deletedAt: Now(),
            deletedBy: Var("currentUser")
          }
        }),
        // 删除用户凭证
        Foreach(
          Paginate(Match(Index("credentials_by_user"), Var("userRef"))),
          Lambda("ref", Delete(Var("ref")))
        ),
        // 删除用户会话
        Foreach(
          Paginate(Match(Index("sessions_by_user"), Var("userRef"))),
          Lambda("ref", Delete(Var("ref")))
        ),
        // 删除用户
        Delete(Var("userRef"))
      )
    )
  )
)

9.2 清理过期数据 #

javascript
// 清理过期的会话数据
Let(
  {
    cutoffTime: TimeSubtract(Now(), 7, "day")
  },
  Foreach(
    Filter(
      Paginate(Documents(Collection("sessions")), { size: 1000 }),
      Lambda("ref",
        LT(
          Select(["data", "createdAt"], Get(Var("ref"))),
          Var("cutoffTime")
        )
      )
    ),
    Lambda("ref", Delete(Var("ref")))
  )
)

9.3 批量删除产品 #

javascript
// 批量删除无库存产品
Let(
  {
    products: Filter(
      Paginate(Documents(Collection("products")), { size: 500 }),
      Lambda("ref",
        Let(
          { doc: Get(Var("ref")) },
          And(
            Equals(Select(["data", "stock"], Var("doc"), 0), 0),
            Equals(Select(["data", "discontinued"], Var("doc"), false), true)
          )
        )
      )
    )
  },
  Foreach(
    Var("products"),
    Lambda("ref",
      Do(
        // 归档产品
        Let(
          { doc: Get(Var("ref")) },
          Create(Collection("products_archive"), {
            data: Merge(
              Select(["data"], Var("doc")),
              {
                originalId: Select(["ref", "id"], Var("doc")),
                archivedAt: Now()
              }
            )
          })
        ),
        // 删除产品
        Delete(Var("ref"))
      )
    )
  )
)

十、删除最佳实践 #

10.1 始终验证 #

javascript
// 好的做法:验证后删除
Let(
  { ref: Ref(Collection("users"), "123456") },
  If(
    And(
      Exists(Var("ref")),
      HasPermission(Var("ref"), "delete")
    ),
    Delete(Var("ref")),
    Abort("Cannot delete document")
  )
)

10.2 记录删除操作 #

javascript
// 记录删除日志
Let(
  {
    ref: Ref(Collection("users"), "user_001"),
    doc: Get(Var("ref"))
  },
  Do(
    // 创建删除日志
    Create(Collection("audit_logs"), {
      data: {
        action: "delete",
        collection: "users",
        documentId: Select(["ref", "id"], Var("doc")),
        data: Select(["data"], Var("doc")),
        deletedBy: CurrentIdentity(),
        deletedAt: Now()
      }
    }),
    // 删除文档
    Delete(Var("ref"))
  )
)

10.3 使用事务 #

javascript
// 使用事务确保原子性
Do(
  // 删除相关数据
  Foreach(
    Paginate(Match(Index("items_by_parent"), parentRef)),
    Lambda("ref", Delete(Var("ref")))
  ),
  // 删除主文档
  Delete(parentRef)
)

十一、总结 #

删除文档要点:

操作 说明
Delete 删除文档
Exists 检查存在
Foreach 批量删除
Do 原子操作
软删除 标记删除

下一步,让我们学习基础查询!

最后更新:2026-03-27