Reputation: 1265
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
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
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
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