Reputation: 830
I have a firestore data model like below
board :{
id: string,
name: string,
cratedAt: Timestamp,
updatedAt: Timestamp,
owner: string,
columns: [{
name: string,
createdAt: Timestamp,
updatedAt: Timestamp,
}]
The problem is I can't add timestamp inside arrays as it isn't supported by firebase. So my options are to go for separate root collection and store the id's inside the "columns" array or go for subcollections. But won't this increase the number of reads and consequently the price/bill of my overall transaction? How do I avoid this?
Upvotes: 5
Views: 2639
Reputation: 629
From the structure of your data, the field board.columns
is a list of object that includes Timestamp data type. Firebase have not yet support inserting Timestamp in a list of objects. To avoid this error you can remove the Timestamp fields.
var json = {board :{
id: string,
name: string,
cratedAt: Timestamp,
updatedAt: Timestamp,
owner: string,
columns: [{
name: string,
createdAt: Timestamp,
updatedAt: Timestamp,
}],
}};
for (var object in (json['columns'])) {
object as Map
..remove('createdAt')
..remove('updatedAt');
}
await doc.set(json);
But somehow if the you really need the Timestamp data, you can consider converting the fields to string or int
Upvotes: -1
Reputation: 114
In Javascript, You can also use new Date(), which automatically converts into firebase timestamp in the firestore database.
Upvotes: 1
Reputation: 83048
Indeed it is not possible to add a timestamp with firebase.firestore.FieldValue.serverTimestamp()
inside an array. See here for more details on the reason why it is not possible. The usual workaround is to change the Array to a Map.
But there is another possible workaround with a Cloud Function:
Since you have, in your doc, two fields which hold a timestamp (createdAt
and updatedAt
), you can assign the value of those fields (generated via FieldValue.serverTimestamp()
) to the array elements, with a Cloud Function called when the doc is created.
The following Cloud Function code shows how to do for one element in the columns
array. It's up to you to adapt it to cover arrays with more than one element.
exports.updateTimeStampsInArray = functions.firestore
.document('myCollection/{docId}')
.onCreate((snap, context) => {
const newValue = snap.data();
const createdAt = newValue.createdAt;
const columnsArray = newValue.columns;
const newColumnsArray = [];
newColumnsArray.push({ name: columnsArray[0].name, createdAt: createdAt });
return snap.ref.update({ columns: newColumnsArray })
});
You need to create the doc as follows:
db.collection('myCollection')
.doc('...')
.set({
createdAt: firebase.firestore.FieldValue.serverTimestamp(),
columns: [{ name: 'TheName' }],
});
As soon as the CF will run, it will populate the Array element with the value of the createdAt
Timestamp.
Upvotes: 8