0
votes

I have a database structure as follows (simplified for purposes of this question):

Collection: registrations
    -> Document: params = {someParameter: "value"}
    -> Document: user_01
        -> Sub-collection: orders
            -> Document: order_AA = {type: "Q1", address: {pincode: "000000", city:"Paris"}
            -> Document: order_AB = {type: "Q2", address: {pincode: "111111", city:"London"}
            ...
    -> Document: user_02
        -> Sub-collection: orders
            -> Document: order_AC = {type: "Q1", address: {pincode: "222222", city:"Berlin"}
            -> Document: order_AD = {type: "Q1", address: {pincode: "333333", city:"Paris"}
            ...

What I want to do: Obtain a list of all the orders across all users within the collection "registrations". (please note that the number of "user" documents is variable over time, and also the number of "order" documents within the sub-collection)

In more words... Query FireStore to find all the available documents (users) within the collection "registrations", and for each of these documents (users) find all the orders in their sub-collection named "orders".

How can I do this in the shortest steps (fewest queries)?

Also, is it essential for me to add a "dummy" field within each "user" document? I have read on StackOverflow that FireStore cannot query sub-collections unless the parent document has "regular" fields. Even after adding a dummy field, I was unable to get it to work.

My most recent effort has been:

let ordersList = [];
await firestore()
    .collection("registrations")
    .get()
    .then((collectionRef) => {          
        collectionRef.forEach((userDoc) => {
            console.log("==", userDoc.id);
            if(userDoc.id.startsWith("user")) {
                userDoc.collections("orders")
                    .get()
                    .then((ordersSnapshot) => {
                        ordersSnapshot.forEach((orderDoc) => {
                            ordersList.push(orderDoc.data());
                        });
                    });
            }
        });
    })
    .catch(error => {
        console.log("Error in retrieving data!");
        console.log('Error: ', error);
    })

I get the error:

Error: [TypeError: userDoc.collections is not a function. (In 'userDoc.collections("orders")', 'userDoc.collections' is undefined)]

2
The collectionGroup suggestion below is good, but note that your solution would work if you fixed (a) it is collection not collections, and (2) that the promises from the inner gets in the loop must be collected and run together with Promise.alldanh
I had actually tried "collection" but got the same error: Error: [TypeError: userDoc.collection is not a function. (In 'userDoc.collection("orders")', 'userDoc.collection' is undefined)] Will anyways move to the collectionGroup approach that you all have recommended. Thanks.Shailesh Appukuttan

2 Answers

1
votes

You should definitely use the collectionGroup() method as described there.

1
votes

You can use a collection group query to query all documents among collections and subcollections with the same name. So, for the subcollection "orders", you can query all documents in those collections using:

firestore().collectionGroup("orders").get()

If you don't want all of the order documents, you will need to add a filter in the same way that you would any other query. You can only filter using the fields available in each orders document (you can't filter per user unless you have a "user" field in the document to use).

I have read on StackOverflow that FireStore cannot query sub-collections unless the parent document has "regular" fields

This is not true. There is no need to have a parent document in place to query its nested subcollections.