Here's my Firebase database Within the "users" collection, I have a document "[email protected]. The document has an array "status". I'm trying to update one of the elements in the "status" array.
I've written the following but I would like to understand if I need to write a separate query to delete first or would this actually update the existing record or add a new record in the "status" array with the same id (1)
final conn = FirebaseFirestore.instance.collection("users")
.doc(email);
conn.update({
"status": FieldValue.arrayUnion([{
"date":"10/15/2022",
"id":1
}]),
});
CodePudding user response:
In general, instead of update
you can use set
with option merge: true
to change only the fields you specify and leave the others alone:
conn.set({'field': 'newValue'}, SetOptions(merge: true));
But in your case the code that you have written will always add a new element to the array status
with the new data even if the id
already exists.
One solution is to go through the existing elements in status
array and update if you find the id
or add a new element.
The other solution is to create a subcollection status
and use set
with the id
. In this case Firestore will do the job and either create a new document or update the existing:
conn.collection('status').doc(1).set({'date': '10/15/2022'});
In both cases please remember that these operations are async so you might want to use await
.
CodePudding user response:
I had to delete and add the new entry. It's very inefficient compared to how we do things in a traditional database i.e SQL UPDATE. Network calls are expensive and should be avoided. I like Peter Koltai's approach but that would force me to refactor my schema which I can't.
Future<void> updateReqStatus(email, id, oldDate, newDate) async {
final conn = FirebaseFirestore.instance.collection("users")
.doc(email);
conn.update({
"status": FieldValue.arrayRemove([{
"date":oldDate,
"id":id
}]),
}).then((value) => print("value"));
conn.update({
"status": FieldValue.arrayUnion([{
"date":newDate,
"id":id
}]),
}).then((value) => print("value"));
}