如何将某个值与Firebase子值进行比较?

时间:2018-12-12 15:12:52

标签: ios swift firebase firebase-realtime-database

说明

我正在将实时数据库与Google的Firebase一起使用,并且试图检查子值是否与某个值匹配。

enter image description here

我有一组存储在Firebase数据库中的用户。 每个用户对象都包含一个令牌字段。

{
  "users" : {
    "-LTTvwvs5OMaKO6pyZb-" : {
      "accountId" : 1001,
      "createdAt" : "2018-12-11 15:22:55",
      "email" : "john@doe.com",
      "fcmToken" : "duhfkNCIKW8:APA91bGgbzVCcagIhIw8DYFN_LVIKcjtyUiZEk0mxd3QLYkxRjQuGXdSfZMPcvw4maytKef-GXMEFrpH_lLz5QY0OV7qvwtyOll9jjKMH0vEWJUGIyp1iGQ4NZIMQE3kmZ-jZ8kF-1Bc",
      "updatedAt" : "2018-12-11 15:22:55"
    },
    "-LTTwH8BdMe6W1lmhb-b" : {
      "accountId" : 1001,
      "createdAt" : "2018-12-11 15:24:22",
      "email" : "john@doe.com",
      "fcmToken" : "e_86qbjpjLE:APA91bHyVEgeH8aZMrn7213ws0-oXeTpdFRwY-FDcAbkQkMnaCdSNp9he6-AvQ0AUIsX-TywAxuWLCZ9BqIRsuyx1ZD9reD6wMeqtfP1swONq-rF6vQzet61DUbLfPXdlZhvxEjI9Cpz",
      "updatedAt" : "2018-12-11 15:24:22"
    },
    "-LTTwNcoaQYri1paUwVD" : {
      "accountId" : 1001,
      "createdAt" : "2018-12-11 15:24:48",
      "email" : "john@doe.com",
      "fcmToken" : "e_86qbjpjLE:APA91bHyVEgeH8aZMrn7213ws0-oXeTpdFRwY-FDcAbkQkMnaCdSNp9he6-AvQ0AUIsX-TywAxuWLCZ9BqIRsuyx1ZD9reD6wMeqtfP1swONq-rF6vQzet61DUbLfPXdlZhvxEjI9Cpz",
      "updatedAt" : "2018-12-11 15:24:48"
    },
    "-LTUv-aBEaQDrvvMrlAG" : {
      "accountId" : 1001,
      "createdAt" : "2018-12-11 18:58:25",
      "email" : "john@doe.com",
      "fcmToken" : "eOaNDdd2DXI:APA91bGzgcudlScng9TuEgSUY9ahA2pXVgl7AKxmkdX9ubw6uA5livNcJUlcI5pHYwn9fI7kc_9od5AbGrXm4wZPul_gI7qcGarTQTwkxq9zEKgovX0nWDDpDtNCLiWIaON6MWu5XLbW",
      "updatedAt" : "2018-12-11 18:58:25"
    }
  }
}

iOS Swift 4

另一方面,我的手机上有 1个令牌

例如

  

“ duhfkNCIKW8:APA91bGgbzVCcagIhIw8DYFN_LVIKcjtyUiZEk0mxd3QLYkxRjQuGXdSfZMPcvw4maytKef-GXMEFrpH_lLz5QY0OV7qvwyOll1jJKQK4K1KJKIK4K

我正在尝试将该令牌与Firebase数据库中的所有令牌进行比较。


代码

func storeToFirebaseDatabase() {

    let ref = Database.database().reference()
    let usersRef = ref.child("users")

    let id = usersRef.childByAutoId().key
    let fcmToken = UserDefaults.standard.string(forKey: "fcmToken")

    consoleLog(fcmToken)

    let values =
        ["accountId": loginAccount.id!,
         "email": loginAccount.username,
         "fcmToken": fcmToken
            ] as [String : Any]

    ref.root.child("users").observe(DataEventType.value, with: { (snapshot) in

        if snapshot.exists() {

            for child in snapshot.children {
                let token = (child as! DataSnapshot).childSnapshot(forPath: "fcmToken").value as! String

                if(token != fcmToken){

                    usersRef.child(id!).setValue(values, withCompletionBlock: { (err, ref) in
                        if err != nil {
                            print(err.self as Any)
                            return
                        }
                        print("Successfully saved user in Firebase DB")

                    })

                    break
                }

            }

        } 


    }) { (error) in
        print(error.localizedDescription)
    }
}

结果

由于某些原因,令牌仍在继续插入,好像我的if-check一直在工作。

如何进一步调试呢?

3 个答案:

答案 0 :(得分:1)

您可以将HashMap()与setValue一起使用,而不是updateChildValues,如果令牌不同,它将覆盖;如果令牌相等,它将不更新令牌并覆盖当前令牌。

而且您可以防止查询数据库以获取该值并将其与if语句进行比较。

您应将此行替换为updateChildValues而不是setValue

usersRef.child(id!).setValue(values....

在这里看看:

https://firebase.google.com/docs/database/ios/read-and-write

从文档中

  

在没有节点的情况下同时写入节点的特定子节点   要覆盖其他子节点,请使用updateChildValues方法。

     

在调用updateChildValues时,您可以更新较低级别的子级   通过指定键的路径来获取值。

答案 1 :(得分:1)

您的问题是,您将if语句中的令牌与每个用户进行比较,但是您需要查看用户是否拥有

ref.root.child("users").observe(DataEventType.value, with: { (snapshot) in

    if snapshot.exists() {

      let tokens =  snapshot.children.forEach { ($0 as! DataSnapshot).childSnapshot(forPath: "fcmToken").value as! String }

        if ! tokens.contains(fcmToken) {

             // no user has that token ,  set the user here
        }
    }

}

答案 2 :(得分:1)

我可能对这个问题有一个误解,但似乎您想要在Firebase中不存在给定令牌的情况下创建用户。

一个简单的查询即可;

let usersRef = self.ref.child("users")
let tokenToCompare = "duhfkNCIKW8APA9..." //abbreviated
let query = usersRef.queryOrdered(byChild: "fcmToken").queryEqual(toValue: tokenToCompare)
query.observe(.value, with: { snapshot in
    if snapshot.exists() {
        print("token exists, do not create user")
        return
    } else {
        print("no existing token found, create user")
    }
})

如果令牌存在,它将打印该消息,并且不会继续。如果令牌不存在,则可以插入代码以创建用户。

...如果您想对所有令牌进行非规范化,请添加一个单独的节点以跟踪现有令牌

existing_tokens
   jasoijaisas9: true
   99i9kmkdodkf: true
   duhfkNCIKW8APA9: true

那么您可以通过简单的观察来避免繁重的查询,因为它重量轻得多。

let existingTokensRef = self.ref.child("existing_tokens")
let tokenToFindRef = existingTokensRef.child("duhfkNCIKW8APA9")
tokenToFindRef.observeSingleEvent(of: .value, with: { snapshot in
    if !snapshot.exists() {
        print("ok to create user")
    } else {
        print("token exists! Dont create user")
    }
})

此技术唯一值得一看的是键中没有special characters