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!
Related
Im trying to create one stream, that is using multiple documents references that are stored and fetched from Firebase Firestore.
Lets say I have two collection named users and documents. When user is created he gets document with his id in users collection with field named documentsHasAccessTo that is list of references to documents inside documents collection. It is important, that these documents can be located in different sub collections inside documents collection so I dont want to query whole documents and filter it, in order to save Firestore transfer and make it faster I already know paths to documents stored in documentsHasAccessTo field.
So for example, I can have user with data inside users/<user uid> document with documentsHasAccessTo field that stores 3 different document references.
I would like to achieve something like this (untested):
final userId = 'blablakfn1n21n4109';
final usersDocumentRef = FirebaseFirestore.instance.doc('users/$userId');
usersDocumentRef.snapshots().listen((snapshot) {
final references = snapshot.data()['documentsHasAccessTo'] as List<DocumentReference>;
final documentsStream = // create single query stream using all references from list
});
Keep in mind, that it would also be great, if this stream would update query if documentsHasAccessTo changes like in the example above, hence I used snapshots() on usersDocumentReferences rather than single get() fetch.
The more I think about this Im starting to believe this is simple impossible or theres a more simple and clean solution. Im open to anything.
You could use rxdart's switchMap and MergeStream:
usersDocumentRef.snapshots().switchMap((snapshot) {
final references = snapshot.data()['documentsHasAccessTo'] as List<DocumentReference>;
return MergeStream(references.map(ref) => /* do something that creates a stream */));
});
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.
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 am using Vue.js and Firebase Firestore. Now I have two collectionsusers and orders. In the orders collection, I have already stored the id of each document of user collection. I now have to fetch the details of the corresponding users from this. How am I supposed to go about it?
This is what I've done so far
let orderRef = db.collection("orders")
orderRef.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if (change.type == "added") {
let doc = change.doc;
this.orders.push({
id: doc.id,
orderData: doc.data().orderData,
user_id: doc.data().user_id,
userInfo: db.collection("users").doc(user_id),
});
}
});
});
I need to store user data in userInfo.Thanks in advance
Firestore doesn't support foreign key like SQL database, so you can't retrieve nested data like SQL.
In Firestore you need to fetch referenced data separately, either you can fetch all users data separately in parallel with orders data and store it in map, or if you don't need users data initially then fetch each users data when needed like when you check details of each order.
I think that you're structuring your data as if you were working in a relational database. Firestore is a no-SQL database that doesn't have any notion of reference, the only thing Firestore understands are key-values, documents and collections, everything else has to me modeled on top of that. See Firestore data model.
In Firestore relationships are usually modeled by storing the id of the document you'd like to "reference". In that sense you might not need to store the 'users' document inside the 'order' but the field 'user_id' would suffice. The caveat is that this data layout comes at the price of having to fetch the 'user_id' from orders before you can fetch the actual user data. You could read more about data denormalization and modeling relationships in articles link1, link2 and this other thread.
Also, it's worth noting that Firestore documents are limited in size to 1MB so with your actual configuration if the amount of info of 'user' documents increases it may get to a point where it would be necessary to reshape your documents structure.
All in all, if you don't want to change your data layout you would need to follow Ked suggestions and first retrieve the 'users' data to inline it into the 'userInfo' field.
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.