How to get data from first collection in Firestore - javascript

I am configuring my Vue/Firebase chat app to save the email address of a registered user in a Firestore collection when the registered user is logged in and submits a message. The Firestore Database looks like the following, with the users added to the "user" collection, and with each user containing a "message" collection:
In my code, I am attempting to add a function that returns the email addresses listed in the "users" collection, as seen in the screenshot:
const contactList = ref([])
const getContacts = () => {
firebase.firestore().collection("users").onSnapshot(snap => {
contactList.value = []
snap.forEach(doc => {
const users = doc.data();
users.id = doc.id;
contactList.value.push(users)
console.log(users)
})
})
},
However, this function does not simply return those email addresses in the user collection, since .collection('users') is the first collection in a chain of docs and collections as indicated in the screenshot. How can I go about returning the list of users in the "users" collection when .collection('users') is the first in a chain of docs and collections?

The document titles are shown in italic, meaning that there are actually no documents with that ID (also shown in the bottom) right and the console merely shows them in order to be able to show the subcollections.
The API won't return such non-existing documents. You'll have to create the document to be able to then read them, for example by running a collection group query over all messages collections and checking if their parent document exists already.
Also see:
Why are non auto-generated document Ids are in italics in Firestore console?
Firestore DB - documents shown in italics
Setting document via subpaths in firebase causes them to show up as italic?
Firestore document/subcollection is not existing

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.

How to access array in Firestore v9

Articles I've read/tried before:
Firestore search array contains for multiple values
Performing a complex query with firestore v9
Firestore collection to array of objects with Firebase v9
FirebaseError: Expected type 'Tc', but it was: a custom Ac object,
https://softauthor.com/firebase-firestore-get-document-by-id/
I have a Firestore that looks like this
The current feature I'm trying to implement is a block list. Whenever you go to the person's profile, you click block, and the person doing the blocking's UID is stored as the doc id and the blocked user's id is added to the "blockedUserId" array
The home page displays all the posts and I've been trying to filter the displayed posts to not include posts from any of the users in that "blockedUserId" array
How do I go about doing this correctly?
Here is the attempted code
query(
collection(getFirestore(fireApp), "posts"),
orderBy("uid"),
where(
"uid",
"not-in",
doc(getFirestore(fireApp), "block", "vXLCRjlhOVW6oFOJvtmML6OolKA2")
)
Firestore queries can only filter on values in the document itself, and values you explicitly pass in to the query. Your doc(getFirestore(fireApp), "block", "vXLCRjlhOVW6oFOJvtmML6OolKA2") creates a DocumentReference, so the query returns documents from posts that don't contain that document reference.
What you want to do instead is:
Load the blocked UIDs
Pass them to the query
So in code:
const myRef = doc(getFirestore(fireApp), "block", "vXLCRjlhOVW6oFOJvtmML6OolKA2");
const myDoc = await getDoc(myRef);
const blocked = myDoc.data().blockedUserId;
const q = query(
collection(getFirestore(fireApp), "posts"),
orderBy("uid"),
where(
"uid",
"not-in",
blocked
)
)
// TODO: call getDocs or onSnapshot on q

cannot get fields from SnapShot in firebase

I'm trying to get the real-time document fields (text and timeStamp) to be displayed from the "first" collection in firestore collection, with the use of onSnapshot. I can verify that the snapshot realtime updation is working, on addition of a new document, it does shows an update. But I cannot access the text and timeStamp in the document.
onSnapshot(collection(db, 'first'), (snapshot) => {
console.log(snapshot.text, snapshot.timeStamp);
});
It just shows undefined to me. Also, I just want to access this database, db only when the user is authenticated. So is there a way to check if the user is authenticated?
To get the data from a document snapshot, you need to call data() on it. In addition, since you're reading an entire collection, you get back a query snapshot that can contain multiple documents, which you also need to handle.
So:
onSnapshot(collection(db, 'first'), (querySnapshot) => {
querySnapshot.docs.forEach((docSnapshot) => {
console.log(docSnapshot.data().text, docSnapshot.data().timeStamp);
})
});
See the documentation on getting data from Firestore and on reading all documents from a collection for more examples like this.

Firebase v9 - Get a Referentiated Document Content

I don't understand why I'm not finding this documentation anywhere.
But I have a collection called users in my Firebase Firestore project. Inside users there are three collections: companies, policies and stores.
In the collection policies I have one store field and one company field that are references to one of that user's store or company.
Ok so as far as now is fine. But now, I'm performing the next query:
const subcollectionSnapshot = await getDocs(collection(db, 'users', 'S3casIyXxdddEAaa1YJL6UjBXLy2', 'policies'));
And the response is the next one:
But now... how can I get the company and store nested documents? How can I "populate" them in order to see their information and access their fields?
Thanks.
It looks like the company and store fields are of type DocumentReference.
In that case you can get a DocumentSnapshot of each of them by calling getDoc() with the DocumentReference:
subcollectionSnapshot.docs.forEach((policyDoc) => {
const companyRef = policyDoc.data()["company"];
const companyDoc = await getDoc(companyRef);
const storeRef = policyDoc.data()["store"];
const storeDoc = await getDoc(storeRef);
...
})
If you have multiple policy documents, you will need to do this for each of them. There is no concept of a server-side join in Firestore (nor in most other NoSQL databases).

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.

Categories