基于不存在文档的 Firestore 事务(集合级锁定不可用)

rah*_*ver 4 database-concurrency google-cloud-firestore

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

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

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

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

Dou*_*son 5

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

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

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