Firebase Get document from subcollection using its ID only - firebase

Is it possible to fetch a document from a subcollection without parent document ids?
We have a structure like:
RootCollection1
-- SubCollection1
-- SubCollection2
- Document1
-- SubCollection3
-- Document2
-- SubCollection2
-- Document3 [different fields with Document1]
App User will only have the Document1 ID.
I tried implementing a collection group query. Notice that SubCollection2 name appears twice and they have different fields/values. I only want to get the document from one SubCollection2.
Is it possible to fetch the data from document1 without the parent doc id from SubCollection1 and RootCollection1.

If you can't locate a document using its full path (knowing the names of all documents and collections in the path), and you can't use a collection group query, then what you're trying to do isn't possible. You can't focus a collection group query to a specific path - they always consider all documents in all collections with the same name.
You have two viable workarounds:
Change the name of the subcollection so that it's unique and does not overlap with subcollections that should not be queried in a collection group query.
Add a field to the document so you can use it in a filter on a collection group query. You will have to be able to identify which documents you are interested in without considering all documents in all subcollections with the same name. For example, if you have a field called "scope", you can narrow the scope of your collection group query like this:
firestore.collectionGroup('coll').where('scope', '==', 'x')
Or you can store the ID of the document as a field in it, and filter for it:
firestore.collectionGroup('coll').where('id', '==', 'id')

This is all you need:
firestore.collection("Task").doc(taskId).collection("SubTask").doc(subTaskId).get();

Related

Firestore - Batch querying nested documents in REST API

There is a way to batch get documents after you specified exactly all the file paths using
https://firestore.googleapis.com/v1/projects/projectName/databases/dbName/documents:batchGet.
And there is a way to get all documents and their fields under a collection by sending a GET to https://firestore.googleapis.com/v1/projects/projectName/databases/dbName/documents/collectionName
I ideally want to make a batch request to get document fields for all documents under an array of collections. Is there a way to do this without knowing the document names of every document I intend to get?
Example
I have a structure like projects/projectName/databases/dbName/documents/Inventory/productId/variantId/*location*
Each productId is a document, and under this it has a collection for each variant, and within that collection are documents for each location, that contains a field count.
For a basket, I want to get all inventory counts for all inventory locations, for each productId/variantId in that bas
It is not possible to get all documents based on an array of collection names.
You can use a collection group query and search all collections of a given name, but then you must know the path of each document you want to read.
Alternatively, you can get all documents under a specific path, but then you can't filter by ID anymore, and the collections have to be under a path - not an array.

Firestore collection group query on document id [duplicate]

This question already has an answer here:
How to perform collection group query using document ID in Cloud Firestore
(1 answer)
Closed 1 year ago.
I am trying to run the following query:
this.db.firestore
.collectionGroup('members')
.orderBy('dateModified', 'desc')
.where(firebase.firestore.FieldPath.documentId(), '==', uid)
But I get the error:
Invalid query. When querying a collection group by
FieldPath.documentId(), the value provided must result in a valid
document path, but 'X6yL5Ko55jSMWhhoQUO91xVYdEH3' is not because it
has an odd number of segments (1).
Is the only way around this to add the document id to the document?
This is not ideal as I have a lot of existing data...
The document id is the uid of the firebase user.
As the error message says, for an index on a collection group the documentId() field values are actually stored as document paths to ensure unique lookups of those values in the index.
If you want to also query on document ID over a collection group, you will indeed have to store the ID as a field value in each document.
Also keep in mind that it is then possible to get multiple documents for the query, even though that is astronomically unlikely if you use the built-in add() operation.
Adding the uid to the document itself is the only possible way at the moment and then query on that field:
this.db.firestore
.collectionGroup('members')
.orderBy('dateModified', 'desc')
.where("uid", '==', uid)
There was a Github issue for the same and explains why that's not possible.
That's pretty much why I sometimes prefer to store a root level collection members. Each document in the collection will have contain the groupID (or whatever your parent collection is meant for). If you use userID as the key for documents in there then it goes easy.
this.db.firestore.collection("members").doc(uid)
So instead of having a path like: /groups/{groupID}/members/{memberID}, the structure will be like: /groups/{groupID} and all the members will be store in the root level collection 'members'. A document in that collection may look like:
// uid as doc key
{
groupId: "groupID",
...otherFields
}
The catch is if a member can join multiple groups you cannot use the userId as the key.

How do I retrieve a subcollection of a document in Firestore

I have a Firestore collection with the following structure:
events > default > participants > participant1
> participant2
> date
etc. So events is a collection, and it has a number of documents with random keys (I've used default as an example). Within "default" there are various fields, but also a subcollection of participants.
When I retrieve events/default I expected to retrieve the list of participants at the same time, but I only get back the fields (date etc) - how do I also get the "participants" collection at the same time?
Firestore queries are shallow and do not consider documents in collections other than the one you are querying. There are no SQL-like "joins" that merge documents from multiple collections.
If you query events, then you will only ever get documents in that collection. If you want participants, you will need to make an additional query, using the full path of the subcollection, including its parent document ID. For example, in JavaScript:
firestore.collection("events").doc(knownId).collection("participants").get()

how do I do a collectionGroup query but get the documents that subcollection is inside of?

how do I do a collectionGroup query but get the documents that subcollection is inside of. My data is structured as: Users (collection) -> UID(doc) -> privateData (collection) -> UID (doc)
and I want to query based on a field in the UID docin the privateData collection, but I want the actual data from the UID Doc in the Users collection
You can't query across multiple collections like this. If you want data from a different subcollection, then your collection group query will need to target that other subcollection instead. This means you would probably have to duplicate the fields from privateData collection into the Users collection. Duplication of field data is common in nosql databases like Firestore.
If you can't duplicate that data for whatever reason (such as privacy), then you would need to query each related document separately, effectively joining each users doc to the matching doc in privateData.
Depending on your data model, you would have to have a reference to the parent document for the sub collection in the child object, or fetch the document and using the documents snapshot, you can call its parent reference
something like this: querySnapshot.docs()[x].snapshot.getRef().getParent()

Firestore: Getting documents sorted by a numeric field contained in the two sub-levels documents

My firm asked me to get all the documents from the root collection, users. They must be sorted according to the value of a numeric field, titled amount, present in a first sub-level document and also in a second sub-level document.
I don't know how to fulfill this aim easily with Firestore NoSQL queries. What would you recommend to me?
Data structure
Here it is:
users
user_1 (document to get and sort)
user_2 (document to get and sort)
Each of these two users is structured like this:
collection_1
document_of_first_level
contains this field: amount
and contains also this collection: collection_2
document_of_second_level
contains this field: amount
So I should get a list containing user_1 and user_2. This is a sorted list. It's sorted according to the two fields both named amount, which are contained under user_1, but also under user_2. These both fields are nested.
They must be sorted according to the value of a numeric field, titled amount, present in a first sub-level document and also in a second sub-level document.
As also #DougStevenson mentioned in his comment, you cannot achieve this with Cloud Firestore. There is no way to get documents from a subcollection (level 1) and another subcollection (level 2) in a single query. Firestore doesn't support queries across different subcollections in one go. Queries in Firestore are shallow, which means they only get items from the collection that the query is run against. A single query may only use properties of documents in a single collection.
So the most simple solution I can think of, would be to query the database twice, once to get the documents within subcollection (level 1) and second to get documents within subcollection (level 2) and then compare them client side.
The idea from your comment is a solution since adding a property under the level 1 document will allow you to query the database just once. In Firestore, you can simply chain multiple where() functions in a single query.

Resources