首页 > 解决方案 > 基于不存在文档的 Firestore 事务(集合级别锁定不可用)

问题描述

基于这个SO answer,我知道 firestore 在事务中没有集合级别锁定。就我而言,在写入集合之前,我必须确保用户集合中的用户名字段是唯一的。为此,我编写了一个执行此操作的事务:

  1. 对 users 集合执行查询以检查是否存在 username=something 的文档
  2. 如果确实存在,则失败并从事务返回错误
  3. 如果它不存在,只需为我要更新/创建的 userId 运行写入操作。

现在这里的问题是,如果两个客户端同时尝试运行此事务,则两者都可能查询集合,并且由于集合未锁定,一个客户端可能会插入/更新集合中的文档,而其他客户端将看不到它。

我的假设正确吗?如果是,那么如何处理这种情况?

标签: google-cloud-firestoredatabase-concurrency

解决方案


您尝试做的事情实际上不可能以原子方式进行,因为不可能对您无法使用 ID 识别的文档进行安全交易。get()这里的问题是,只有当您可以添加或修改特定文档时,事务才是“安全的” 。由于您不能get()使用文档中的字段值来创建文档,因此您不知所措。

如果您想确保 Firestore 中任何内容的唯一性,则需要将该唯一性编码到文档 ID 本身中。在最简单的情况下,您可以使用用户名作为新集合中文档的 ID。如果你这样做了,你的交易可以简单地get()通过用户名输入所需的文件,检查它是否存在,如果不存在则编写文件。否则,交易可能会失败。

请记住,由于 Firestore 中的文档 ID 存在限制,如果您的用户名可能违反规则,您可能需要对该用户名进行转义或编码。


推荐阅读