My db structure is like this:
domain -> user uid -> user data
if I try to add data like this:
await FirebaseFirestore.instance
.collection(path)
.doc(firebaseUser.uid)
.collection(collectionName)
.add({...});
where path is the user domain, the database shows like this:
telling me that The document does not exists, it will not appear in queries or shapshots. But if I add the same data by auto id like this:
await FirebaseFirestore.instance
.collection(path)
.add({...});
it works like the second document in picture. Why is this happening?
Look at how the documents in this collection are displayed in an italic font in the Firestore console: This means that these documents are only present as "container" of one or more sub-collection but that they are not "genuine" documents.
As a matter of fact by doing
await FirebaseFirestore.instance
.collection(path)
.doc(firebaseUser.uid)
.collection(collectionName)
.add({...});
You create a doc in the collectionName (sub)collection but not in the path collection.
On the other hand, with
await FirebaseFirestore.instance
.collection(path)
.add({...});
you do create a doc in the path collection.
So if you need to have a document in the path collection AND in the collectionName (sub)collection you need to create these two documents and not only the "child" one.
DETAILED EXPLANATIONS:
Let's take the example of a doc1 document under the col1 collection
col1/doc1/
and another one subDoc1 under the subCol1 (sub-)collection
col1/doc1/subCol1/subDoc1
Actually, from a technical perspective, they are not at all relating to each other. They just share a part of their paths but nothing else.
You can very well create subDoc1 without creating doc1.
A side effect of this is that if you delete a document, its sub-collection(s) still exist. Again, the subcollection docs are not really linked to the parent document.
Related
I am working on an attendance project. So, I have nested documents and collections. But problem is that:
Firestore not listing documents that don't have fields. Firebase db structure Pic
it only listing documents that have fields.
I am doing this in JavaScript.
db.collection("Attendence").get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
});
Firestore not listing documents that don't have fields.
That's the expected behavior. The documents that I see listed in italics ("CG1", "CSE A1", and "DG2") are not actually documents present in the collection.
The documents that are present in the "Attendence" collection and are writen in italics mean that there exist some subcollections with other documents added under those document IDs.
There is no query that can return those documents since they don't exist. So in other words, you have just reserved some IDs for some documents in that collection and then create a subcollection under it. These kinds of documents are visible in the Firebase Console because you might want to navigate into their subcollections.
One thing to remember, in Cloud Firestore documents and subcollections don't work like filesystem files and directories. If you create a subcollection under a document, it doesn't implicitly create any parent documents. Subcollections are not tied in any way to a parent document.
This is the thing I want to accomplish: I'm building a web shop. The web shop has a React Front-end. The front-end fetches 5 collections from Firestore and displays all the items from the collection array on the shop page. A user selects an item on the shop page. I send the item fields such as (price, name, quantity, id) to my express server and the server makes a checkout session of the item fields. The user goes to a Stripe checkout form and is sent back to my front-end by Stripe when the payment is complete. I listen for that event on my server and when then want to update the quantity field of the item in Firestore.
But how do I query Firestore for this item? Is there a way to query Firestore with only this id field (or name field)? Some something like:
db
.collection('collections')
.where('id', '===', 1)
Or do I need to save the document id (of the collection) as a field inside the item map and also send that to Stripe? Or is there a better way to do this? I can't find anything online about this.
Here is a screenshot of Firestore.
Please forgive my beginner question. I'm still learning React, Firestore and Node.js.
First be sure you are sticking to the Firestore terminology correctly. There are collections and there are documents.
Collections you access via a path such as:
collRef = db.collection("products")
collRef = db.collection("products").where("quanity_on_hand", ">", "0")
collRef = db.collection("products").doc("12345").collection("purchase_history")
The latter instance can also be accessed via collRef = db.collection("products/12345/purchase_history").
In all the above cases you will get back a CollectionReference.
Documents you access such as:
docRef = db.collection("products").doc("12345")
docRef = db.doc("products/12345")
This returns you a DocumentReference for the document whose ID is "12345" in the collection "products".
So for your code example above, you want to use docRef = db.doc("collections/1") to get back the DocumentReference for the item you are after. (Or, alternatively, you could use: docRef = db.collection("collections").doc("1")
If you stick with the code that you have above, you'd get back a CollectionReference then you'd need to fetch the data with .get(), then extract the resulting documents (that will just be a single document), then work with that. Oh...and you will need to put an "id" field into all of your documents because the document's ID value (the "name" of the document) is not part of the document by default so if you want to use .where("id", "==", "1"), then you need to add an "id" field to your document and populate it correctly.
If you go with docRef = db.doc("collections/1"), you are querying for the document directly and will get back a reference to just that one. No need for extra fields, nor extracting a single document from a result set.
I'm trying to return all document IDs in a specific collection. I'm writing this in Javascript for a web application.
I made this function, and call it where it is needed.
function getUserList() {
var rootRef = firebase.database().ref();
var db = firebase.firestore();
//var docRef = db.collection("Users");//.doc(getUserID()).collection("userControl").doc("UserStatus") //EXAMPLE: /Users/UUID/userControl/UserStatus
db.collection('Users')
.get().then(function(querySnapshot) {
size = querySnapshot.size // will return the collection size
console.log(size);
querySnapshot.forEach(function(doc) {
console.log(doc.id);
});
});
}
However when I check the console log for the data, I only ever see 6 out of 8 documents. There are 8 documents total, but the count and log of doc.id only shows 6. can be seen in screenshot (blanked one ID out for reasons).
If I specify one of the missing documents .get.collection('Users').doc('UUID HERE')... it reads that document without issue.
Most of these documents are uploaded from an IOS app, with the exception of mine (blurred out), the UID template. If I manually edit the document, ie add an extra field, etc the document appears in the search, but for documents straight from the IOS app, they aren't appearing unless speficifed.
I'm not sure how to go about fixing this, or why this issue is occuring.
The documents you see listed in italics ("AB47..." and "DCBC...") are not actually documents present in the collection. The italics means that there are subcollections with other documents organized under that document ID. No query will ever match those documents, since they don't exist. You might have deleted them without deleting all the documents in all of their subcollections. But they remain visible in the console because you might want to navigate into their subcollections.
I am trying to achieve this for the friend request functionality in my data structure for sent requests, but I am unable to:
Essentially I am trying to pull this off from the Realtime Database in the Cloud firestore:
Above reqId1 and reqId2 are automatically generated Id's.
Its quite easy to pull this off in the Realtime db as I can just use the push() method.
The issue is not creating a random number, it is that I am unable to create a document with an autoID inside the userId document in which I shall store the data.
I have tried this:
sendRequest() {
const uid = auth().currentUser.uid;
firestore()
.collection('Sent_Reqs')
.doc(`${uid}`)
.collection(`${this.autoId()}`)
.add({
targetId: this.userId,
sentAt: new Date(),
});
}
But the above doesn't do any good because it nests the data two levels inside the document(uid).
Please help me
Thank you
The data structure on Firestore is always in pairs of collection and then document in there. The collection names are usually fixed/hard-coded names, while the document names are usually generated (or based on the data).
You can't immediately nest documents under another document, they must always be in a named collection. If there's no reason for you to have multiple subcollections, you can just pick any subcollection name that makes sense for you.
For example:
Sent_Requests
(uid)
Requests
(request_id)
Here Sent_Requests and Requests are collection names, (uid) and (request_id) are document names. The Requests collection is not really helpful, but needed to satisfy the Firebase requirements.
It's part of your document data. I don't this firebase can help you on that.
If you are structuring the database this way just to fetch the request sent by particular user easiy. I would like to suggest another structure as follows:
Sent_Request (collection)
|-AutoID1 (document, this ID you can generate with help of firebase)
|- targetUser : value
|- sentAt : value
|- requestSentBy : userId
|-AutoID2 (document, this ID you can generate with help of firebase)
|- targetUser : value
|- sentAt : value
|- requestSentBy : userId
My Cloud Firestore looks like this:
users
├────random_id_1───{name, email, ...}
├────random_id_2───{name, email, ...}
...
└────random_id_n───{name, email, ...}
I want to update a document of users given I have an unique identifier for it that is NOT the random id of the document (suppose, for example, the name is unique and I want to use it as identifier).
How can I update a document identifying it by a field of it?
Firestore can only update documents for which it knows the complete reference, which requires the document ID. On your current structure, you will have to run a query to find the document. So something like:
firebase.firestore().collection("users")
.where("name", "==", "Daniel")
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(document) {
document.ref.update({ ... });
});
});
If you have another attribute that is unique, I'd always recommend using that as the IDs for the documents. That way you're automatically guaranteed that only one document per user can exist, and you save yourself having to do a query to find the document.