【问题标题】:Checking document exists in Firestore transactions检查文件是否存在于 Firestore 事务中
【发布时间】:2018-08-01 13:35:30
【问题描述】:

我有一个简单的 Firestore 事务,它首先读取以验证文档是否存在,如果不存在,则执行一些写入操作。

代码 sn-p 看起来像这样

Firestore.firestore().runTransaction({ (transaction, errorPointer) -> Void in    
  let snapshot: DocumentSnapshot
  // First check if user already exists.
  let userRef = firestore.document("users/\(user.uid)")
  do {
    try snapshot = transaction.getDocument(userRef)
  } catch let fetchError as NSError {
    errorPointer?.pointee = fetchError
    return
  }
  if !snapshot.exists {
    // Document doesn't exist. Start write operation...
    ...

当文档不存在时,getDocument 似乎没有返回有效的快照,而是引发了错误。我不想依靠错误来断定文档不存在(因为它可能会与其他错误混淆)。

在 Firestore 事务中验证文档是否存在的正确方法是什么?

【问题讨论】:

    标签: swift firebase transactions google-cloud-firestore


    【解决方案1】:

    好吧,你可以尝试做这样的事情:

    Firestore.firestore().runTransaction({ (transaction, errorPointer) -> Void in    
      let snapshot: DocumentSnapshot
      if let snapshot = try? transaction.getDocument(userRef) {
        if snapshot.exists {
         // Snapshot already exists!
         return
        }
      } 
      print("Document doesn't exist. Let's get to work!")
      // Perform write operations here
      ...
    

    虽然取决于您要执行的操作,但使用安全规则执行此操作可能会更容易。

    例如,以下规则将允许您创建一个新的用户对象,但绝不会覆盖它。

    match /users/{userID} {     
      allow create: if request.auth.uid == userID;
      allow update: if false;
    }
    

    然后你可以尝试每次设置用户对象,它只会第一次成功。但是,很明显,这只有在您真的不希望您的客户端在将来更新用户对象时才有效。

    【讨论】:

    • 谢谢。我担心的是依靠getDocument 抛出错误是否是确定文档不存在的正确做法。目前,如果文档不存在,它甚至不会到达snapshot.exists if 语句。它只会抛出一个错误。 getDocument 在事务上的这种行为不同于 getDocument 在 DocumentReference 上返回的行为(它正确读取快照并且可以按文档说明使用 exists 属性)。我发现两者之间的区别令人困惑。
    • @jayOrange 也一样,你的理解变了吗?
    • 在类似的注释中,很高兴知道当且仅当文档不存在时才会引发错误。如果存在相关文档时引发任何其他错误,则代码可能会执行不必​​要的覆盖。
    猜你喜欢
    • 2018-06-21
    • 2018-03-16
    • 1970-01-01
    • 2020-01-12
    • 1970-01-01
    • 2021-08-21
    • 2019-01-21
    • 2021-11-09
    相关资源
    最近更新 更多