2

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

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

I am using a collection group query to retrieve all the orders under "item_A" (across all users). I am able to get this to work via:

let orders = [];
await firestore()
    .collectionGroup("orders_item_A")
    .get()
    .then(function (querySnapshot) {
        querySnapshot.forEach(function (doc) {
            console.log(doc.id, ' => ', doc.data());
            orders.push(doc.data());
        });
    })

But now I need to refine the above to be able to filter for orders from specific cities (e.g. Paris). So I tried adding a 'where' clause as follows:

let orders = [];
await firestore()
    .collectionGroup("orders_item_A")
    .where("address.city", "==", "Paris")
    .get()
    .then(function (querySnapshot) {
        querySnapshot.forEach(function (doc) {
            console.log(doc.id, ' => ', doc.data());
            orders.push(doc.data());
        });
    })

But this fails, and I get the following message:

Error: [Error: [firestore/failed-precondition] Operation was rejected because the system is not in a state required for the operation's execution. Ensure your query has been indexed via the Firebase console.]

I have already set up a composite index on my FireStore database with the following details:

Collection ID = orders_item_A

Fields indexed = address.city Ascending type Ascending

Status = Enabled

I am not sure what I am doing incorrectly. I wondered if the problem is with using an object property within the 'where' clause (which should not be the problem). So I also tested with a simpler query such as:

.where("type", "==", "A1")

But this too failed. What am I doing wrong?

Community
  • 1
  • 1
  • Are you sure that the value of type is "item_A"? Also, check the android native log, you will get a link to create the index directly which for wherever reason doesn't show up on RN. – Aawaz Gyawali Jun 02 '20 at 17:29
  • Your query is using a dynamic collection group name and we can't see the value of `type`. Please edit the code to hard code the collection group name, so we can all be certain that your index matches your query. – Doug Stevenson Jun 02 '20 at 17:34
  • @AawazGyawali: Not sure I understood. The value of "type" (in the above example) will be either "A1" or "A2". You are right, RN doesn't show the link for creating the index. I tried doing "adb logcat" but found the exact same error message as posted in the question. Is there another way to find the link to create the index? – Shailesh Appukuttan Jun 02 '20 at 17:37
  • @DougStevenson: Oops, that was a typo . I have corrected it in the question now. (Also had tested with hard-coded values in my queries, but had the same results). – Shailesh Appukuttan Jun 02 '20 at 17:40
  • Also... not sure I understood what you meant by "and we can't see the value of `type`". It is either "A1" or "A2" in the above database snapshot. Or were you asking something else? – Shailesh Appukuttan Jun 02 '20 at 17:46

2 Answers2

7

I figured out the problem. My mistake was apparently in having made a "Composite" index (as I mentioned in the question) as it was the opening page on clicking "Indexes". I should have made a "Single field" index:

enter image description here

After deleting my existing composite index, I made a new "single field" index with details as:

enter image description here

Click 'Next' and on the next screen, "enable" one of the options under 'Collection group scope' (I chose Ascending):

enter image description here

It is important to do the above, or else the query will not work. And then everything worked as expected, with my original code:

let orders = [];
await firestore()
    .collectionGroup("orders_item_A")
    .where("address.city", "==", "Paris")
    .get()
    .then(function (querySnapshot) {
        querySnapshot.forEach(function (doc) {
            console.log(doc.id, ' => ', doc.data());
            orders.push(doc.data());
        });
    })

Note: If you happen to delete a particular "index", it takes some time (upto 10 minutes on some occasions) to be ready. During this period you will get an error if trying to create an index for the same entry. So wait, and try again after some time.

0

maybe related question, can we filter by the parent collection name?

for example if we had a structure like this

Collection: item_A
    -> Document: params = {someParameter: "value"}
    -> Document: user_01
        -> Sub-collection: orders_item_A
            -> Document: order_AA = {type: "A1", address: {pincode: "000000", city:"Paris"}
            -> Document: order_AB = {type: "A2", address: {pincode: "111111", city:"London"}
            ...
    -> Document: user_02
        -> Sub-collection: orders_item_A
            -> Document: order_AC = {type: "A1", address: {pincode: "222222", city:"Berlin"}
            -> Document: order_AD = {type: "A1", address: {pincode: "333333", city:"Paris"}
            ...
Collection: item_B
    -> Document: params = {someParameter: "value"}
    -> Document: user_03
        -> Sub-collection: orders_item_A
            -> Document: order_AA = {type: "A1", address: {pincode: "000000", city:"Paris"}
            -> Document: order_AB = {type: "A2", address: {pincode: "111111", city:"London"}
            ...
    -> Document: user_04
        -> Sub-collection: orders_item_A
            -> Document: order_AC = {type: "A1", address: {pincode: "222222", city:"Berlin"}
            -> Document: order_AD = {type: "A1", address: {pincode: "333333", city:"Paris"}
            ...

can we fetch the collection group from item_B only?

Amr Ahmed
  • 203
  • 3
  • 12