首页 > 解决方案 > 交易可以在收款时使用吗?

问题描述

我正在使用 Firestore 并尝试通过使用事务删除 Flutter 应用程序中的竞争条件。

我有子集合,最多添加 2 个文档。

竞争条件意味着可能会添加超过 2 个文档,因为使用了客户端代码setData。例如:

Firestore.instance.collection(‘collection').document('document').collection('subCollection’).document(subCollectionDocument2).setData({
  ‘document2’: documentName,
});

我正在尝试使用事务来确保最多添加 2 个文档。因此,如果在事务运行时集合发生了变化(例如将新文档添加到集合中),事务将失败。

但是我读过文档,似乎事务更多地用于在文档中设置字段的竞争条件,而不是在子集合中添加文档。

例如,如果尝试实现:

Firestore.instance.collection(‘collection').document('document').collection('subCollection').runTransaction((transaction) async {

}),

给出错误:

错误:没有为“CollectionReference”类定义方法“runTransaction”。

事务可以用于监控子集合的更改吗?

有人知道其他解决方案吗?

标签: firebasetransactionsgoogle-cloud-platformfluttergoogle-cloud-firestore

解决方案


事务可以用于监控子集合的更改吗?

Firestore 中的事务通过所谓的比较和交换操作进行。在事务中,您从数据库中读取文档,确定其当前状态,然后根据该状态设置其新状态。当您为整个事务完成此操作后,您将整个当前状态和新状态文档包发送到服务器。服务器然后检查存储层中的当前状态是否仍然与您的客户端开始时的状态相匹配,如果是,它会提交您指定的新状态。

知道了这一点,在事务中监控整个集合的唯一方法就是将该集合中的所有文档读入事务中。虽然这在技术上对于小型集合来说是可行的,但它的效率可能非常低,而且我从未见过在实践中这样做过。再说一次,对于您集合中的两个文档,在事务中简单地读取它们可能是完全可行的。


请记住,虽然事务仅确保数据一致,但并不一定限制恶意用户可以执行的操作。如果要确保集合中的文档不超过两个,则应查看服务器端机制。

最简单的机制(基础设施方面)是使用 Firestore 的服务器端安全规则,但我认为这些规则不会限制集合中的文档数量,正如 Doug 在他对限制文档数量的回答中所解释的那样firestore 规则中的子集合

在这种情况下,最可能的解决方案是(正如 Doug 所建议的)使用 Cloud Functions 将文档写入子集合中。这样,您可以简单地拒绝来自客户端的直接写入,并在受信任的环境中运行的 Cloud Functions 代码中强制执行您想要的任何业务逻辑。


推荐阅读