I am new to Firebase cloud firestore. My database structure looks something like in the picture below. So, basically I have got a document for 'Liked' which tracks the timestamp at which user has liked the content. It has got 'chapter' as subcollection and inside each chapter there are sub-chapters which has the actual timestamp. Now I want to retrieve all the liked data ordered by the timestamp. I am not sure how can I achieve this!
You may use orderBy() to specify the sort order for your data like shown in the following example:
db.collection("liked").orderBy('timestamp').get()
I would also suggest you to follow this doc, it demostrates how to set up Cloud Firestore, add, read data and secure data.
UPDATE
I created the following database to replicate your scenario:
reprod(collections)/
test1(document)/
liked(collections)/
0(document)/
type(filed)
To stream the timestamps in ascending order I iterated manually to the doc and fetched the data ordered by timestamp:
reprod = db.collection(u'reprod').document(u'test1').collection(u'liked')
timestamps = reprod.stream()
for doc in timestamps:
print(f'{doc.id} => {doc.to_dict()}')
To do that I used the Firestore documentation on how to retrieve data and how to order data.
Related
My cloud firestore database has an "orders" collection and in HTML I have a 'save' button to add document(s) into that "orders" collection upon clicking. Now, using add will assign auto-generated ID for each document.
What if I want to customise such ID by timestamp? So that the document created yesterday will be assigned an index as '1', and the following document created will be '2', etc...
What you're trying to do is not compatible with the way Cloud Firestore was designed. Firestore will not assign monotonically increasing numbers for document IDs. This just doesn't scale massively as required by Firestore and would introduce performance bottlenecks.
If you want to be able to sort documents by timestamp, the best strategy is to add a timestamp field to each document, then use that field in an ordered query.
Note that you could try to write a lot of code to get this done the way you want, but you are MUCH better off accepting the random IDs and using fields to filter and order data.
in some case, when you need to save several docs in different collection due to an event occurs, it's better to same all docs with same id in different collections with single firestore server's timestamp. you get the timestamp like below:
const admin = require('firebase-admin')
const ts = admin.firestore.Timestamp.now().toMillis().toString()
by doing this, when you need to read all those docs, you only need to query once to get timestamp, then read all other doc by timestamp directly.
it should be faster than query the timestamp inside document fields for each collections
I made a simple chat app using Flutter. My app is functioning perfectly fine (getting and dumping data into firebase) but once my messages get into my database, they are randomly ordered resulting in my msgs getting displayed in a random order.
I have tried reversing the SnapshotQueue in my Flutter code but that did not help...
You will need to attach document names to your documents before uploading them.
I think you are experiencing this issue because your documents are being given Auto Ids.
Try using the current timestamp as the document name. this will help arrange documents in order according to time uploaded.
Firestore.instance.collection(CollectionName).document(Timestamp.now()).setData(messageMap);
i hope this is what you need. if not. Please share your code that uploads the message to database.
Add a field like datePublished = DateTime.now() to each message document as
it gets created to
store the timestamp of when the message was created
Then you can use datePublished field to order your documents of your QuerySnapshot like this:
QuerySnapshot snapshot = await collection.orderBy('datePublished', descending: true).get();
now your messages are arranged in chronological order from the latest
to earliest.
I just migrated my data from Realtime Database to Firestore and started to use firestore but I had a function to push() in Realtime Database and also save push().key so I changed it to add() or set() for Firestore but I realize that add().id set().id is totally random key unlike Realtime Database push().key is organized like the later push().key is always behind previous push().key. I must save data and it must be organized like push(). Is there any solution to generate keys that are organized like push().key??
//I tried 2 options
//option 1
ref.add({something:something}).then((gref)=>{ref.doc(gref.id).set({key:gref.id},{merge:true})})
//option 2
var ref = db.doc();
ref.set({something:something,key:ref.id})
both generates unorganized keys unlike push().key
I searched, read documents and I realized that Firestore doesn't provide organized key as Realtime Database but I found solution for this. If someone need organized key, you have to use timestamp and sort as ascending or descending.
just like
// when you want to save data..
ref.set({timestamp:firebase.firestore.FieldValue.serverTimestamp()})
// and if you want get data..
db.collection('something').orderBy("timestamp", "asc").get()
// it will sort automatically!
I'm trying to make an Activity log system or history for my docs, so every time a field is modified in a document i want to record or save that so i can see after changes history made on each document.
how i can achieve that ? i don't want to save the full doc on each change and then have tons of duplicated docs, if possible i just want to get the changed field (ex. name: 'john' -> name: 'jack').
i don't want to save the full doc on each change and then have tons of duplicated docs
Once a document has changed it becomes a new document. So you won't have duplicate documents unless you make changes that were previously made. Please also note that in Cloud Firestore there are no field-level permissions or access to a document. It's the entire document, or nothing. So if you want to change a field within a document for example from:
userName = "John"
into
userName = "Jack"
You'll will get the entire document and not only the userName property that has been changed.
Cloud Firestore listeners fire on the document level. There is no way to get triggered with just particular fields in a document.
If you want to get notified only of specific fields, consider adding an extra collection with documents that only contain those fields. This sort of data duplication is quite common in NoSQL solutions such as Firestore and for that, I recommend you see this video, Denormalization is normal with the Firebase Database for a better understanding. It is for Firebase real-time database but same principles apply to Cloud Firestore.
For a database schema you can also take a look at my answer from this post.
The best way to achieve something like this is to store the before and after changes happening to the doc, in a new document, which you can add in a subcollection. The changes are available with cloud functions onUpdate trigger. I have written in depth about this topic on my blog, have a look.
https://blog.emad.in/audit-logs-for-firestore-documents/
You can obtain this by creating a cloud function that triggers on all document updates in all collections:
--trigger-resource=projects/$PROJECT_ID/databases/(default)/documents/{collection_id}/{document_id}
In the cloud function you can obtain all the updated fields and their values through the data object.
Python example:
def main(data, context):
# Extract resource
resource = context.resource
resource_split = resource.split('/')
collection_name = resource_split[-2]
document_id = resource_split[-1]
# Get old fields
data_old_values = data['oldValue']
data_old_values_fields = data_old_values['fields']
# Get updated fields
data_updated_mask = data['updateMask']
data_updated_fields = data_updated_mask['fieldPaths']
# Get new field values
data_new_values = data['value']
data_new_values_fields = data_new_values['fields']
# `data_updated_fields` is a list of the fields that has been changed
# `data_old_values_fields` is a dictionary with the old values of the document
# `data_new_values_fields` is a dictionary with the new values of the document
I am working on angular 5 with firebase firestore.I inserted data into fire-store collection/document/collection/document/collection/document then set data the last document.But at the time retrieving data I am giving only first collection name then I want complete root data.but I am getting only field in it.
https://firebase.google.com/docs/firestore/query-data/get-data
checkout:List subcollections of a document
As we know querying in Cloud Firestore is shallow by default. This type of query isn't supported, although it is something Google may consider in the future.