how to add new data to existing map in firebase flutter - firebase

here is the firebase document data
I want to add a new map value to the purchased-id. this is the current code
FirebaseFirestore.instance.collection('users').doc(userID).set({
'purchased-id': {
widget.head: widget.id,
}
});
but with this code the map value is replaced,
how do I add another map value to the existing map
like this

I think need merge: true to update the map with its new value.
FirebaseFirestore.instance.collection('users').doc(userID).set({
'purchased-id': {
widget.head: widget.id,
}
}, SetOptions(merge: true));
Reference: https://firebase.google.com/docs/firestore/manage-data/add-data#update_fields_in_nested_objects
Also to differentiate with .set and .update, have a look at this answer: https://stackoverflow.com/a/47554197/11566161

Related

How to update Map Value in Flutter Firebase Firestore

I have a Map object in my document data. Like Below
I have to add a new user bid to the same map without erasing old data but the code I used was replacing the whole Map with the new value. Any suggestions on how to achieve my goal.
FirebaseFirestore.instance.collection('products')
.doc(widget.product.uid).update({
'bids': {
auth.currentUser?.email:
currentPrice.toString()
}
});
You need to use dot notation to update a nested field:
const userEmail = auth.currentUser?.email;
FirebaseFirestore.instance.collection('products')
.doc(widget.product.uid).update({
'bids.${userEmail}': currentPrice.toString()
});
Dot notation allows you to update a single nested field without overwriting other nested field. If you update a nested field without dot notation, you will overwrite the entire map field
References:
Update fields in nested objects
FlutterFire Documentation
To update fields with . in their keys:
var fPath = FieldPath(["bids", "user.name#domain.tld"]);
FirebaseFirestore.instance.collection('products').doc(widget.product.uid).update(fPath, currentPrice.toString());

Flutter/Firebase : I want to update existing values, but new values are being created

I'm working on a flutter project and this is my code :
String vl = store.reference().child("Volunteers/Aadithya").push().key;
vlRef = FirebaseDatabase.instance.reference().child("Volunteers/Aadithya");
vlRef.child(vl).update({
"Contributions": int.parse(count)+1,
}).then((_) {
}).catchError((onError) {
Scaffold.of(context)
.showSnackBar(SnackBar(content: Text(onError)));
});
Contributions is a data record inside Aadithya. I need to update its value alone. But what happens is, a new sub-record is being created inside Aadithya, with contributions being its data type
Please help:
You are adding it to a child with random ID. You don't need the push key. Try this:
vlRef = FirebaseDatabase.instance.reference().child("Volunteers/Aadithya");
vlRef.update({
"Contributions": int.parse(count)+1,
}).then((_) {
}).catchError((onError) {
Scaffold.of(context).showSnackBar(SnackBar(content: Text(onError)));
});
.child(vl) means you are adding another child node with that value.

Firestore adding to map without deleting

Im trying to add to a map field but when i try this line it replaces the current fields under the map. How can I add new elements to a map without replacing the current values?
var document = await db.collection("trips").document(widget.tripInfo.documentID).updateData({
'members': {
name : id,
},
});
If you want to update a nested field, use dot notation:
db.collection("trips").document(widget.tripInfo.documentID)
.updateData({ 'members.name': id })
Also see the Firebase documentation on updating fields on a nested object.

How to add a value to list field in firebase?

I have a field of type array in my firebase database and I want to add to it new values.
What code I want :
Firestore.instance.collection('lists').document(123).setData({
'myList': FieldValue.add(**myValue**);
});
This should work:
Firestore.instance.collection('lists').document(123).updateData({
'myList': FieldValue.arrayUnion(['el1', 'el2'])
});

Can I prevent Firebase set() from overwriting existing data?

If I do this, all is good with my itemRef:
itemRef.child('appreciates').set(newFlag);
itemRef.child('id').set(newId);
other properties of itemRef remain BUT child_changed is called twice
If I do this:
itemRef.set({appreciates:newFlag,id:newId});
child_changed is called only once but my other properties are destroyed.
Is there a workaround besides the clumsy one of repopulating the entire reference object?
Thanks,
Tim
The Firebase update() function will allow you to modify some children of an object while leaving others unchanged. The update function will only trigger one "value" event on other clients for the path being written no matter how many children are changed.
In this example, you could do:
itemRef.update({appreciates:newFlag,id:newId});
Documentation for update() is here.
You can create a rule that will prevent overwrites if data already exists.
Reproduced here from Firebase docs Existing Data vs New Data
// we can write as long as old data or new data does not exist
// in other words, if this is a delete or a create, but not an update
".write": "!data.exists() || !newData.exists()"
Now .update takes care of it, you can change existing data or add new one without affecting the rest of data you already had there.
In this example, I use this function to set a product as sold, the product has other variables with data and may or may not have sold or sellingTime but it doesn't matter cos if it doesn't exist will create them and if it does, will update the data
var sellingProduct = function(id){
dataBase.ref('product/'+id).update({
sold:true,
sellingTime: Date.now(),
}).then (function(){
alert ('your product is flaged as sold')
}).catch(function(error){
alert ('problem while flaging to sold '+ error)
})
}
Though you can use update, you can also use set with merge option set to true:
itemRef.set({ appreciates:newFlag, id:newId }, { merge: true });
This will create a new document if it doesn't exists and update the existing if it does.
I've been trying to do this having a structure like the following:
The problem I was having was when running say set on specific fields such as name, description and date all of the other child nodes would then be removed with the following:
return (dispatch) => {
firebase.database().ref(`/gigs/${uid}`)
.set({ name, description, date })
.then(() => {
dispatch({ type: GIG_SAVE_SUCCESS });
Actions.home({ type: 'reset' });
});
};
Leaving only the name, description and date nodes but using the following the specific nodes are updated without removing the other child nodes i.e. members, image etc:
return (dispatch) => {
var ref = firebase.database().ref(`/gigs/${uid}`);
ref.child('name').set(name)
ref.child('description').set(description)
ref.child('date').set(date)
.then(() => {
dispatch({ type: GIG_SAVE_SUCCESS });
Actions.home({ type: 'reset' });
});
};

Resources