Rohan Dalvi
Rohan Dalvi

Reputation: 1265

Updating nested objects firebase

From the Firebase note:

Given a single key path like alanisawesome, updateChildren() only updates data at the first child level, and any data passed in beyond the first child level is a treated as a setValue() operation. Multi-path behavior allows longer paths (like alanisawesome/nickname) to be used without overwriting data. This is why the first example differs from the second example.

I am trying to use a single function createOrUpdateData(object) in my code. In case of update, it updates first level children properly, but if I have nested object passed, then it deletes all other properties of that nested object.

Here's the code:

function saveUserDetails(email,object){
        var hashedEmail = Utilities.getHashCode(email);
        var userRef = ref.child(hashedEmail);
        return $q(function(resolve,reject){
            return userRef.update(object, function(error){
                if(error){
                    reject(error);
                }else{
                    resolve("Updated successfully!");
                }
            });
        });
    }

So if I pass:

{
   name: 'Rohan Dalvi', 
   externalLinks: { 
      website: 'mywebsite'
   }
}

Then it will delete other properties inside externalLinks object. Is there a cleaner and simpler way of avoiding this?

In short, how do I make sure nested objects are only updated and that data is not deleted.

Upvotes: 21

Views: 11098

Answers (3)

Shadi Abu Hilal
Shadi Abu Hilal

Reputation: 288

To update nested object/map/dictionary in firebase database, you can use Firestore.Encoder to class/struct that is Codable.

Here is a Swift code example:

Models:

import FirebaseFirestore
import FirebaseFirestoreSwift

// UserDetails Model
class UserDetailsModel: Codable {
   let name: String, 
   externalLinks: ExternalLinkModel
}    

// UserDetails Model
class ExternalLinkModel: Codable {
   let website: String
}

Calling Firebase:

    import FirebaseFirestore
    import FirebaseFirestoreSwift

    let firestoreEncoder = Firestore.Encoder()

    let fields: [String: Any] = [
        // using firestore encoder to convert object to firebase map
        "externalLinks": try! firestoreEncoder.encode(externalLinkModel)
    ]

    db.collection(path)
        .document(userId)
        .updateData(fields, completion: { error in
             ...
    })

Upvotes: 0

D W
D W

Reputation: 358

This question provides a more recent solution that works with cloud firestore.

Rather than using "/", one may use "." instead:

var userRef = ref.child(hashedEmail);
var updateObject = {
   name: 'Rohan Dalvi', 
   "externalLinks.website": 'mywebsite'
};
userRef.update(updateObject);

Upvotes: 19

David East
David East

Reputation: 32624

You can use multi-path updates.

var userRef = ref.child(hashedEmail);
var updateObject = {
   name: 'Rohan Dalvi', 
   "externalLinks/website": 'mywebsite'
};
userRef.update(updateObject);

By using the "externalLinks/website" syntax in the object literal it will treat the nested path as an update and not a set for the nested object. This keeps nested data from being deleted.

Upvotes: 30

Related Questions