How to update value in Firebase with childByAutoId

2019-04-02 01:35发布

When I create objects in Firebase, I use childByAutoId. How can I update these specific objects later? I'm having trouble obtaining the value of the key Firebase automatically updates. Snapshot.key just returns "users". Here's my JSON structure:

{
  "users" : {
    "-KQaU9lVcUYzIo52LgmN" : {
      "device" : "e456f740-023e-440a"
      "name: "Test"
    }
  },

How can I get the -KQaU9lVcUYzIo52LgmN key? I want to update the device child. Here's what I have so far. It currently creates a completely separate snapshot with a single child.

self.rootRef.child("users").queryOrdered(byChild: "name").queryEqual(toValue: self.currentUser).observeSingleEvent(of: .value, with: { (snapshot) in
    let key = self.rootRef.child("users").childByAutoId().key
    let childValues = ["device": device]
    self.rootRef.child("users").child(key).updateChildValues(childValues)

Edit: device is a string set further up in the code. Not defined in this scope (to make it easier to read for this question).

3条回答
冷血范
2楼-- · 2019-04-02 02:04

When you get Snapshot.key, it returns "users" because that is the overall key for your snapshot. Everything inside of "users" in your snapshot is considered the value.

You need to iterate over the child layers to dig down to "device".

Try this:

rootRef.child("users").observeSingleEventOfType(.Value, withBlock: { (snapshot) in 
    if let result = snapshot.children.allObjects as? [FIRDataSnapshot] {
        for child in result {
            var userKey = child.key as! String
            if(userKey == userKeyYouWantToUpdateDeviceFor){
                rootRef.child("users").child(userKey).child("device").setValue(device)
            }
        }
    }
})

This code will do the following:

  1. Gets snapshot of your reference (the key for that would be 'users').
  2. Gets all the children (your user keys) and assigns them as another snapshot to 'result'.
  3. Checks each key one at a time until it finds the key you want (for example, if you look for user with the key "-KQaU9lVcUYzIo52LgmN", it will find it on the first iteration in your example code you posted).
  4. Once it finds that key, it sets the value for the device inside that key with the line rootRef.child("users").child(userKey).child("device").setValue(device).

Of course, you will need to store all your user keys when you make them. You can maybe use SharedPreferences on the device for this, but if it gets cleared for any reason then that data will just be sitting there. You could also store it on internal storage for your app, but SharedPreferences is what I would use.

Hope this helps!

查看更多
做个烂人
3楼-- · 2019-04-02 02:04

snapshot has a property key which is

The key of the location that generated this FIRDataSnapshot.

And as you can see you are getting one (snapshot) by calling observeSingleEvent(of: .value, with: { (snapshot)...

so instead of let key = self.rootRef.child("users").childByAutoId().key

try to call let key = snapshot.key

childByAutoId().key always generates new unique key based on timestamp, that's why you are creating new child, not updating the one you want

Hope that works

查看更多
爷的心禁止访问
4楼-- · 2019-04-02 02:05

I adapted Ryan's answer to my own issue (kinda similar) and figured out a way to update your device ID directly without needed to know/store the AutoID key generated by Firebase :

reference = Database.database().reference().child("users")

reference.observeSingleEvent(of: .value, with: { (snapshot) in
                            if let result = snapshot.children.allObjects as? [DataSnapshot] {
                                for child in result {
                                    if child.childSnapshot(forPath: "device").value as? String == self.yourDeviceIDVariable {
                                        print("### Device exists in Firebase at key = \(child.key)")
                                        let childKey = child.key
                                        self.reference.child(childKey).child("device").setValue(yourNewDeviceID)
                                    }
                                }
                            }
                        })
查看更多
登录 后发表回答