【问题标题】:How to compare a certain value against Firebase child values?如何将某个值与 Firebase 子值进行比较?
【发布时间】:2019-05-13 17:39:21
【问题描述】:

说明

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

我有一组存储在 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 斯威夫特 4

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

例如

"duhfkNCIKW8:APA91bGgbzVCcagIhIw8DYFN_LVIKcjtyUiZEk0mxd3QLYkxRjQuGXdSfZMPcvw4maytKef-GXMEFrpH_lLz5QY0OV7qvwtyOll9jjKMH0vEWJUGIyp1iGQ4NZIMQE3kmZ-jZ8kF-c"

我正在尝试比较那个令牌????????到我的 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 完全正常。

如何进一步调试?

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

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

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

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

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

    看这里:

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

    来自文档

    同时写入一个节点的特定子节点 覆盖其他子节点,使用 updateChildValues 方法。

    调用updateChildValues时,可以更新下级child 通过指定键的路径来获取值。

    【讨论】:

    • 您建议我们不要仅仅为了检查比较而进行查询-我理解正确吗?
    • 当您使用 updateChildValues 时,它将转到您想要的孩子设置令牌值,如果该值已经存在,它将不会覆盖或更新它,如果该值存在但它与那个不同你想设置,它会更新当前值而不覆盖它
    • 我明白了,我会使用updateChildValues,但是如果我不一直检查到底部,我怎么知道要更新哪个子值?
    • .child(id!) 将完成这项工作,因为您正在访问每个 userID ,如果它们不同,updateChildValue 将更新或不更新
    • 正如我所建议的,你不应该使用 .setValue,而应该使用 updateChildValues,但你需要一张地图来将其设置为参考,查看文档说明它是如何完成的,我更像是一个 Android比 IOS 的家伙,但我认为两个平台的解决方案是相同的,因为逻辑不会改变
    【解决方案2】:

    您的问题是您将 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
            }
        }
    
    }
    

    【讨论】:

    • 我确定我的用户对象将始终具有 fcmToken 列。
    • 您对我现有的代码有什么其他建议吗?你也认为我应该使用updateChildValues
    • 您的要求是确保在添加之前没有用户拥有相同的 fcmtoken?如果是这样,那么以上就足够了
    【解决方案3】:

    我可能误解了这个问题,但如果给定的令牌在 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

    【讨论】:

      猜你喜欢
      • 2023-01-05
      • 1970-01-01
      • 1970-01-01
      • 2019-04-03
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-12
      相关资源
      最近更新 更多