【问题标题】:How to query a firestore database correctly?如何正确查询firestore数据库?
【发布时间】:2021-06-26 17:12:35
【问题描述】:

我编写了这个函数,它接收用户名和密码字符串。然后它会查询 firestore 数据库中的用户集合,以查看是否使用了该用户名。如果查询返回任何文档,它会返回并离开闭包。如果它没有找到文档,它会创建具有指定数据的用户。该函数正确写入数据库,但查询逻辑不起作用,因此多个用户具有相同的用户名。

这里是与函数相关的相关代码:

func createAccountWith(_ username: String, _ password: String){
    
        let userPath = "users"
        let store = Firestore.firestore()
        let userDB = store.collection(userPath)
        
        
        //Query the DB for the given username. If we find that username, then throw an error
        userDB.whereField("username", isEqualTo: username).getDocuments(){ (querySnapshot, err) in

            if let error = err{
                print("Error querying DB: \(error)")
                return
            }
            
            for document in querySnapshot!.documents{
                if document.exists{
                    return
                }
            }



        }
        
        //set data if no document exists
        userDB.document("\(UUID().uuidString)").setData(
            [
                "username":username,
                "password":password
            ]
        
        )
        
        
    }

【问题讨论】:

  • WWDC async await video 非常擅长解释“旧”方式、新方式以及如何使闭包与新方式协同工作。

标签: google-cloud-firestore swiftui


【解决方案1】:

在异步代码中,认为出现在另一行之前的代码行执行是错误的。在 OP 的情况下...

func createAccountWith(_ username: String, _ password: String){
    
        let userPath = "users"
        let store = Firestore.firestore()
        let userDB = store.collection(userPath)
        
        // *** THIS RUNS FIRST
        //Query the DB for the given username. If we find that username, then throw an error
        userDB.whereField("username", isEqualTo: username).getDocuments(){ (querySnapshot, err) in

            // *** THIS RUNS THIRD, A "LONG TIME" AFTER
            if let error = err{
                print("Error querying DB: \(error)")
                return
            }
            for document in querySnapshot!.documents{
                if document.exists{
                    return
                }
            }

        }
        // *** THIS RUNS SECOND, RIGHT AWAY, BEFORE THE GET COMPLETES
        //set data if no document exists
        userDB.document("\(UUID().uuidString)").setData(
            [
                "username":username,
                "password":password
            ]
        )

    }

所以要修复,在发现没有匹配的用户名之后,在闭包内创建用户...

func createAccountWith(_ username: String, _ password: String){
    
        let userPath = "users"
        let store = Firestore.firestore()
        let userDB = store.collection(userPath)
        
        
        //Query the DB for the given username. If we find that username, then throw an error
        userDB.whereField("username", isEqualTo: username).getDocuments(){ (querySnapshot, err) in

            if let error = err{
                print("Error querying DB: \(error)")
                return
            }
            
            for document in querySnapshot!.documents{
                if document.exists{
                    // these returns return from the block, not the containing function
                    return
                }
            }
            // no matching user found 
            //set data if no document exists
            userDB.document("\(UUID().uuidString)").setData(
                [
                    "username":username,
                    "password":password
                ]
            )

        }
        // code placed here runs before the getDocuments completion block
        // so nothing here can depend on the result of the get
    }

【讨论】:

  • 有没有办法让某些代码行在执行之前等待其他东西完成?
  • 另外,有没有什么好的资源可以推荐给我,可以帮助我理解如何异步设计代码?我理解这个概念(两段代码同时执行,但是数据库查询比简单的 if 语句需要更长的时间才能完成),但我想知道这个事实应该如何改变我的编程
  • @BruceJagid - 你的意思是,还有另一种方法吗? swift 中的常用方法是传递一个在异步任务之后运行的完成块。我们强制用户 create 在 get 之后运行的方式是将 create 放在 get 的完成块中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
  • 1970-01-01
  • 2021-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多