使用Swift的Firebase查询未按预期工作

时间:2017-02-07 13:59:54

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

我试图查询我的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结构中最顶层的用户执行。

最重要的是,我尝试了多种参考变化,但根本没有返回任何内容。

任何帮助都表示赞赏! 感谢

3 个答案:

答案 0 :(得分:1)

您需要合并queryOrderedByChild:queryEqualToValue:才能获得正确的结果:

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

query.observe(.childAdded, ...

答案 1 :(得分:0)

尝试替换

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

let ref2 = ref1.queryEqual(toValue: queryText)

然后致电:

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

由于您现在不是在寻找某个用户,而是为所有用户寻找

答案 2 :(得分:0)

此问题是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执行此操作,但在这种情况下似乎并不需要它。 (请参阅Frank的答案,因为它是问题中发布的结构的正确解决方案)

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

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)"
      }
   })