【问题标题】:Firebase Query using Swift not working as expected使用 Swift 的 Firebase 查询未按预期工作
【发布时间】:2017-06-24 19:26:34
【问题描述】:

我正在尝试查询我的 Firebase 数据库以查找具有特定名称或电子邮件地址的用户。我找到了几个如何做到这一点的示例,所有这些示例似乎都相对容易理解,但没有一个对我来说起到预期的作用。

这是我的 json 数据结构的示例。

{
 "allUsers" : {
    "uid0001" : {                        
       "userInfo" : {
          "email" : "firstName1.lastName1@email.com",                  
          "firstName" : "firstName1",
          "lastName" : "lastName1",          
          "uid" : "uid0001"
          }
       },
    "uid0002" : {        
       "userInfo" : {
          "email" : "firstName2.lastName2@email.com",
          "firstName" : "firstName2",
          "lastName" : "lastName2",          
          "uid" : "uid0002"
          }
       }
    }    
}

这是我尝试查询数据库的示例函数

func performQuery(forName queryText:String)
{
    let key = "firstName"

    let ref1 = firebaseDatabaseManager.allUsersRef.queryOrdered(byChild: queryText)
    let ref2 = firebaseDatabaseManager.allUsersRef.queryEqual(toValue: queryText, childKey: key)

        //ref.observeSingleEvent(of: .childAdded, with: {(snapshot) in
        ref1.observe(.childAdded, with: {(snapshot) in

            let userId = snapshot.key

            if let dictionary = snapshot.value as? [String: AnyObject]
            {
                if let userInfo = dictionary["userInfo"] as? [String:AnyObject]
                {
                    if
                        let email           = userInfo["email"]         as? String,
                        let firstName       = userInfo["firstName"]     as? String,
                        let lastName        = userInfo["lastName"]      as? String
                    {
                        let user = User.init(withFirst: firstName, last: lastName, userEmail: email, uid: userId)
                    }
                }
            }
        })
}

你可以在这里看到我有两个例子来说明我如何构建 ref 和两个例子来说明我如何观察引用,尽管我已经尝试了我能想到的所有可能的组合。

如果我使用 ref.observe(.... 无论 queryText 是否实际存在,该块都将为节点上的所有用户执行。 如果我使用 ref.observeSingleEvent(of:.... 该块将为 json 结构中的最顶层用户执行。

除此之外,我还尝试了几种参考变体,它们什么都不返回。

感谢任何帮助! 谢谢

【问题讨论】:

    标签: ios json swift firebase firebase-realtime-database


    【解决方案1】:

    尝试替换

    let ref2 = firebaseDatabaseManager.allUsersRef.queryEqual(toValue: queryText, childKey: key)
    

    let ref2 = ref1.queryEqual(toValue: queryText)
    

    然后调用:

    ref2.observe(.childAdded, with: {(snapshot) in
    

    因为现在你不是在寻找某个用户,而是在寻找所有用户

    【讨论】:

      【解决方案2】:

      你需要结合queryOrderedByChild:queryEqualToValue:来得到正确的结果:

      let query = firebaseDatabaseManager.allUsersRef
          .queryOrdered(byChild: "userInfo/" + key)
          .queryEqual(toValue: queryText)
      
      query.observe(.childAdded, ...
      

      【讨论】:

        【解决方案3】:

        这个问题是 Firebase 结构(不必要地)太深了。

        你拥有的是

        "allUsers" : {
            "uid0001" : {                        
               "userInfo" : {    <- This is the issue
                  "email" : "firstName1.lastName1@email.com",                  
                  "firstName" : "firstName1",
                  "lastName" : "lastName1",          
                  "uid" : "uid0001"
                  }
               },
        

        应该(可能)是

        "allUsers" : {
            "uid0001" : {                        
                "email" : "firstName1.lastName1@email.com",                  
                "firstName" : "firstName1",
                "lastName" : "lastName1"
            }
        }
        

        可能不需要在 uid0001 节点中包含 userInfo 节点。

        此外,您可能不需要存储在节点中的 uid 以及将其用作键 - 当节点返回时,您始终可以从 snapshot.key 获取每个用户的 uid。

        话虽如此,您实际上可以使用deep query 执行此操作,但在这种情况下似乎不需要它。 (请参阅弗兰克的回答,因为它是问题中发布的结构的正确解决方案)

        并使用我建议的结构查询特定的名字

        let fName = "firstName1"
        let queryAllUsersRef = allUsersRef.queryOrdered(byChild: "firstName")
                                          .queryEqual(toValue: fName)
        
        //get all of the users with firstName1
        queryRef.observeSingleEvent(of: .value, with: { snapshot in
        
              //snapshot may return more than one user with that first name
              //  so iterate over the results
              for snap in snapshot.children {
                   let userSnap = snap as! FIRDataSnapshot //each user is it's own snapshot
                   let userKey = commentSnap.key //the uid key of each user
                   let userDict = userSnap.value as! [String:AnyObject] 
                   let email = userDict["email"] as! String
                   print("uid: \(userKey) has email: \(email)"
              }
           })
        

        【讨论】:

          猜你喜欢
          • 2016-10-14
          • 1970-01-01
          • 2012-11-13
          • 2021-07-15
          • 2015-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多