Where condition in firestore subcollection in ReactJS [duplicate] - reactjs

This question already has answers here:
How to fetch all documents from a firebase collection where each document has some sub collection and in sub collection there is a document?
(2 answers)
Closed 6 months ago.
My data is stored in Firestore in below model.
My Problem is, I want to get schoolid of logged-in email id.
Data Model:
instituteData->schoolid->users->email->data
What I tried
const q = query(collection(db, "instituteData"), where("email", "==", "abc#gmail.com"));
const querySnapshot = await getDocs(q);
querySnapshot.forEach((doc) => {
// doc.data() is never undefined for query doc snapshots
console.log(doc.id, " => ", doc.data());
});
Screenshot of Data Structure
Screenshot of Data Structure

Firestore queries can only filter on data in the documents that they return. So unless the email field is. inside the school documents, your query won't work.
The common workarounds are to:
Replicate the email of each user in their school document, and using an array-contains query to then find the school.
Using a collection group query on all users collections to find the correct user(s), and then going up the ref.parent().parent() chain of the document snapshots to find the school for each result.
Also see:
firestore query document that have a collection contains a document
How to query Firestore subcollection's document's data?
How to fetch all documents from a firebase collection where each document has some sub collection and in sub collection there is a document?

As far as I know, there are no inner queries in firebase like we have in SQL, and your approach looks like the SQL table approach, clearly, your structure will not work well in firebase. You shouldn't make SQL-like structure in NoSQL, I learned this hard way.
one solution I can think of is to store the id of parent collections in child collection and all of their documents.
Basically, you are passing ids parent to all children. ¯\(ツ)/¯
In your case
you should store schoolId in all its students, then you can directly get that document with getDoc() query and schoolId will be there already.
Hope this helps 😁

Related

Is there any way to retrieve multiple documents by ID using FireStore (FlutterFire)?

In my flutter/dart app, I am using FlutterFire to sync data with my FireStore database.
I have a list of IDs from document (of the same collection) that I want to retrieve from FireStore.
I am trying to do the following:
await FirebaseFirestore.instance.collection('groups').doc([id1, id2, id3, id4]).get();
But ".doc()" won't accept a list as a parameter for the document ID to look for.
I tried with the "where" method like this:
await FirebaseFirestore.instance.collection('groups').where("id", whereIn: [id1, id2, id3, id4]).get();
But it won't work since the "id" isn't a field in the documents (it is their name/identifier).
The only two solutions I can think about are:
Doing one request per document I want to retrieve (not ideal at all)
Adding a field "id" in the documents that store the same information as their name/identifier (I don't like duplicating data that can end mismatching)
The third one (ideal IMO) would be to enable .doc to accept lists/arrays, so you can search for a list of documents you know the identifier of.
Am I missing something? Does anybody know any other solution?
THANKS!
(asked the same question here)
I found a solution here!
So adapting it to my case it looks like this:
await FirebaseFirestore.instance.collection('groups').where(FieldPath.documentId, whereIn: [id1, id2, id3, id4]).get();
Be aware that there is a limit of 10 to the number of values/IDs you can use in the search.

Flutter Firebase where query

Lets imagine I have a list with Document ids e.g
List documentIds = ["Tj4EB68R1CwBYKPfWzcm","fExzUQbpzjEbGyE8mKDa","yPQvLLN7hkDFCjKN6mky"];
Now I want to get all Documents that match that id.
How can I do that?
You're looking for a whereIn query, which looks like this:
FirebaseFirestore.instance
.collection('yourdocuments')
.where(FieldPath.documentId, whereIn: documentIds)
.get()
.then(...);
The list of document IDs can be up to 10 long, so if you have more than 10 document IDs you'll need to run multiple queries and merge the results in your application code.
See also:
The FlutterFire documentation for querying Firestore
The reference documentation for Query.where()
The reference documentation for FieldPath.documentId.

Firestore firebase

I want to query all data by _id in fields receiver ( as image below), I use firestore firebase. Can anyone help me?
If you want to query documents for values nested in map fields, you can use dot notation to find that value:
firestore.collection("notifications").where("receiver.id", "==", x)

How to count number of element in array data in Firestore?

I am studying Firestore with React.
After I added the array data into the firestore, I am trying to count the certain element in array of data in the document.
Like the picture I attached, there are several documents includes array data.
I want to count the number of CS 34800 in class array from all documents.
What is the best way to get it?
Thank you!
enter image description here
There are no counting or aggregating operations on Firebase, so that way you have it now, you will have to query for all the documents that match your criteria, then count the number of documents in your result set.
You can use an "array_contains" operator to get all the documents where an array contains some value.
collectionRef.where("class", "array-contains", "CS 34800").get()
.then(querySnapshot => {
const count = querySnapshot.size
});
If you need to get a count without making a query for documents, you'll have to maintain that yourself for every string that you could possibly need to count, which is an entirely different problem.

How do I perform multiple reads in Firebase Cloud Firestore efficiently?

I have a collection in Firebase's Cloud Firestore database with subcollections like so:
myCollection
doc1
statistics
doc1
doc2
doc3
doc2
statistics
doc1
doc2
doc3
statistics
doc1
doc2
doc3
doc4
doc4
statistics
and so on.
Based off of a query, I pull maybe doc1, doc2, and doc4 from the collection, for example. Now, for each of those, I need to query their respective subcollections for relevant statistics.
My solution in my AngularJS app so far has been:
/**
* Gets aggregate views for queried docs.
* #param {![firebase.firestore.DocumentSnapshot]} docs - the queried documents
*/
$scope.getTotalViews = (docs) => {
let promises = [];
docs.forEach(doc => {
promises.push($scope.getTotalDocumentViews(doc.id));
});
$q.all(promises).then(totalViewsArray => {
// TODO: Sum the array to get aggregate views for queried documents
// Only outputs some of the time
console.log(totalViewsArray);
});
};
/**
* Gets all view statistics from a given document's subcollection.
*/
$scope.getTotalDocumentViews = (id) => {
let deferred = $q.defer();
firebase.firestore().collection("myCollection").doc(id).collection("statistics").where("type", "==", "view").get().then(snapshot => {
deferred.resolve(snapshot.size);
});
return deferred.promise;
};
The problem I am running into is since there can be many documents that are returned by the query on myCollection, looping through all of these and querying their subcollections seems grossly inefficient. Not only that but, while the above code does succeed some of the time, a lot of the time it throws the error:
Uncaught (in promise) Error: transaction closed
I have also tried to perform the multiple subcollection queries in a transaction, but this has not worked as well since I am not retrieving just one doc, but rather querying for potentially hundreds from the subcollection.
How do I efficiently query the subcollections of some set of multiple documents?
I think the same applies here as to most other NoSQL databases (and definitely the Firebase Realtime Database): if you want to be able to efficiently get the count of something from the database, you should store that count as a property and update it continuously (in this case) views occur. Trying to read hundreds of documents just to determine their count isn't going to scale.
So consider adding a view_count property to each document, and increment that (likely with a transaction) as you record views.

Resources