Please help me solve this, I would like to update the fields using dot notation, using set() but each time I run with the below implementation. I have the fields added to firestore as e.g studentInfo.0.course.0.courseId
instead of updating the already existing ones.
Json sample as it sits in firestore
"schoolId": "school123",
"studentInfo": [
{
"studentId": "studentI23",
"regDate": "2020-04-18",
"course": [
{
"courseId": "cs123",
"regDate": "2020-05-28",
"status": "COMPLETED"
}
]
}
],
"registered":"yes"
}
Code logic
const query = firestore.collection('users').where('registered', '==', 'yes')
const students = await query.get()
students.forEach(student => {
firestore.doc(student.ref.path).set({
'studentInfo.0.studentId': '345','studentInfo.0.course.0.courseId': '555'
}, { merge: true })
})
On the docs I can only find updating nested objects but not nested array objects.
Please help me solve this, I would like to update the fields using dot notation, using set() but each time I run with the below implementation. I have the fields added to firestore as e.g studentInfo.0.course.0.courseId
instead of updating the already existing ones.
Json sample as it sits in firestore
"schoolId": "school123",
"studentInfo": [
{
"studentId": "studentI23",
"regDate": "2020-04-18",
"course": [
{
"courseId": "cs123",
"regDate": "2020-05-28",
"status": "COMPLETED"
}
]
}
],
"registered":"yes"
}
Code logic
const query = firestore.collection('users').where('registered', '==', 'yes')
const students = await query.get()
students.forEach(student => {
firestore.doc(student.ref.path).set({
'studentInfo.0.studentId': '345','studentInfo.0.course.0.courseId': '555'
}, { merge: true })
})
On the docs https://firebase.google./docs/firestore/manage-data/add-data#update_fields_in_nested_objects I can only find updating nested objects but not nested array objects.
Share Improve this question asked Oct 19, 2020 at 13:57 SabetiGSabetiG 4094 silver badges8 bronze badges2 Answers
Reset to default 9It is indeed not possible to update a single element in an array using dot notation, or otherwise. To update an array you'll need to:
- Read the document
- Get the current value of the array from it
- Determine the new array contents
- Write the entire updated array back to the database.
The only alternative array operations are array-union
and array-remove
, which add and remove unique elements to/from the array - essentially treating it as a mathematical set. But since you are looking to update an existing element, these operations are of no use here.
Also see:
- Firestore Update single item in an array field
- Firestore update specific element in array
- How to update an "array of objects" with Firestore?
There is no direct way to update the as stated in the article. You can either run a transaction to get the latest array value and then updating the array with the final array value. That would be as below:
await firestore.runTransaction((transaction: Transaction) => {
const students: Array<Students> = firestore
.collection("users")
.where("registered", "==", "yes");
students.forEach((student) => {
const firebaseDoc = firestore.doc(student.ref.path);
transaction.set(
firebaseDoc,
{
"studentInfo.0.studentId": "345",
"studentInfo.0.course.0.courseId": "555",
},
{ merge: true }
);
});
});
Inside transaction I am getting the array first and then updating each values as per my need. This will make the whole operation atomic so the issues mentioned in the article will not e.
Alternatively, you can also model your firestore database as below
"schoolId": "school123",
"studentInfo": {
"studentI23": {
"studentId": "studentI23",
"regDate": "2020-04-18",
"course": [
{
"courseId": "cs123",
"regDate": "2020-05-28",
"status": "COMPLETED"
}
]
}
},
"registered":"yes"
}
Above I have changed the array to map, since in map you can update the each field based on dot notation fields(doc), hence. you can achieve your end result. This solution will avoid any transaction query and will be faster