How to create document with subcollection - javascript

I can't find how to create a new document without any fields, but one subcollection - messages (and this message collection would have some fields).
This is what I want to do. But I don't want to create subcollection in document which already exist. I want to create new document and subcollection in it.
Honestly I stopped on that :
let chatRef = db.collection("chat_event").add({
})

This answer will greatly help.
let chatRef = db
.collection("chat_event").document("chat1")
.collection("messages").document("message1");
If you don't want to hardcode the parent document's id or if you want a firestore generated id. Then get the id first from firestore's createId() function.
let chatEventId = db.createId();
let chatRef = db
.collection("chat_event").document(chatEventId)
.collection("messages").document("message1");
You could still use auto-generated id for the subcollection's document:
let chatEventId = db.createId();
let messageId = db.createId();
let chatRef = db
.collection("chat_event").document(chatEventId)
.collection("messages").document(messageId);
Note that firestore's autogenerated IDs are entirely random and consequently the documents are not stored in any chronological order. If you will in anyway need some ordering, you could add timestamps to those documents either when you insert data or you update the document with the timestamp info.
docRef.update({
timestamp: firebase.firestore.FieldValue.serverTimestamp()
});
With that, you can order chronologically both in the console and in your own queries.
Check out this answer for more information on auto-generating IDs

Related

Firestore Database: How to search for an email in multiple documents

I need to find the ID of a document, and I must do it by comparing the email that each document contains.
This is my database:
For example, I know the email "mipaciente2#gmail.com", and I don't know what document that email is in, what query do I have to do to search each document until I find the one that contains that email?
You just need to have a subcollection reference which is the patients and then create a query using the where() method to find the email field with a specific value. Though, I'm not sure what version you are using. I'll just give the modular and the namespaced versions. See sample snippets below:
Web Version 9 (modular):
import { collection, query, where } from "firebase/firestore";
// For `user's-document-id`, I guess you have it.
const patientsRef = collection(db, "users", "<user's-document-id>");
// Create a query against the collection.
const q = query(patientsRef, where("email", "==", "mipaciente2#gmail.com"));
Web Version 8 (namespaced):
var patientsRef = db.collection("users").doc("<user's-document-id>").collection("patients);
// Create a query against the collection.
var query = patientsRef.where("email", "==", "mipaciente2#gmail.com");
For more information, you may want to check out this documentation.

Fetching documents of sub-collections in firestore

I'm trying to fetch sub-collection documents from my firestore database.
Collection Imgs:
My current code:
const fetchHighlight =async()=>{
const Highlight = []
const HighlightDbId = await
db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk').collection('4C4kd2QnaQhcp9knexkW').get()
console.log(HighlightDbId)
}
React.useEffect(()=>
{
fetchHighlight ()
}, [])
You forgot to fetch your query at the end of your chain, and the subcollection 4C4kd2QnaQhcp9knexkW does not exist, it's the id of a document in the subcollection you're trying to access. The right subcollection ID was hBYWvZ3KN3NLLrucTpryETQZnz2.
To sum up, you could go this way:
const yourDocument = (await db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk')
.collection('hBYWvZ3KN3NLLrucTpryETQZnz2').doc('YOUR_DOC_ID').get()).data()
or this way:
const yourDocument = (await db.collection('highlights/2SCS2S0JnzngWEiYkHNk/hBYWvZ3KN3NLLrucTpryETQZnz2')
.doc('YOUR_DOC_ID').get()).data()
Edit
If you want to fetch only the first document of the subcollection you can go this way:
const yourDocument = (await db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk')
.collection('hBYWvZ3KN3NLLrucTpryETQZnz2') // subcollection ref
.orderBy("createdAt", "asc") // index
.limit(1) // limit the size of your response
.get()) // send the request and wait for it (you could also use '.then()' here)
.docs[0] // get the first doc of the array
.data() // retrieve the doc's data use `.id` instead if you want its id
And if you want to get the first subcollection of a doc you should go this way with the listCollections method:
const subcollectionId = (await db
.doc('highlights/2SCS2S0JnzngWEiYkHNk')
.listCollections())[0] // retrieve the first subcollection `.id`
Note that this only works with the node.js library, if you're attempting to do your query fore the front-end, it will fail. Then you should simply put a reference of your subcollection inside your parent doc by an update when creating your subcollection in the first place:
// const HighlightDbId = creating you subcollection
db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk').update({
subcollection: HighlightDbId
});
And simply retrieve the field subcollection when you need to fetch data from its subcollection.
I fixed this problem by adding the last doc :
db.collection('highlights').doc('2SCS2S0JnzngWEiYkHNk').collection('4C4kd2QnaQhcp9knexkW').doc('XXXXXXXX').get()

Firestore query with only a field inside an array

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.

Wildcard queries for documents in Firestore subcollections

my Firestore database is organized as follows:
(col = collection, doc = document)
-data (col)
-userid -> random number (doc)
-clients (col)
-clientid -> random number (doc)
-clientid -> random number (doc)
-userid(doc)
-clients (col)
-clientid -> random number (doc)
...
and I need to read all data inside a specific "clientid" document just asking the user to insert it's clientid random number.
I wonder if I can read this data with wildcard syntax like in the rules of database:
var clientid = "65486649466"
var clientdata = db.collection("data").doc({userid}).collection("clients").doc(clientid);
Or there is another way of doing this?
Thanks
There are no wildcards in Firestore client queries. You need to provide the exact values for all collection and document IDs needed to make the query.
If you need to query across all subcollections called "clients" in the entire database (including those nested under "data", and elsewhere), you can instead use a collection group query to find those documents:
const query = db.collectionGroup("clients")
query.get()...
This query will return all the documents among all the subcollections named "clients". Unfortunately, you can't filter this query based on the document ID of each client document. What you would have to do for this is also write the client document ID as a field in each document. Suppose you've done that, and the field name is called "id":
const query = db.collectionGroup("clients").where("id", "==", clientid)
query.get()...
This will give you all the "clients" subcollection documents where the "id" field is clientid.

Get document id from Firestore after fetching document

How can I get the document id of a firestore document after successfully fetching the document. I am fetching user data from firestore collections like this
const ref = await db.collection('users').where('phone', '==', phone)
.where('password', '==', password).get();
I have a valid document after executing this query.
const data = ref.docs[0].data();
How can I get the auto generated document id? I tried data.id and data.path, it is returning undefined.
How can I access the auto generated id?
In my code, it was actually trying to get the data id, instead of document id
i got the document id by adding const docRefId = ref.docs[0].id;
In addition to Sony's answer, you can get the document reference as well:
const docRefId = ref.docs[0].ref;

Categories