1

I am trying to build a Firestore query in flutter which filters restaurant results based on the cuisine requested.

Based on the answer from Firestore query where map contains string by Lucas Aschenbach, I have designed my database so that the cuisines are listed in a common sub-collection

data model

and my query is:

final Query locations = FirebaseFirestore.instance
        .collection('locations')     
        .where('cuisines.$id.exists', isEqualTo: true);

I have added read access to the sub-collection:

match /locations/{l} {
      allow read: if true;
      allow write: if request.auth.token.role == 'admin';
    }
match /locations/{l}/cuisines {
      allow read: if true;
      allow write: if request.auth.token.role == 'admin';
    }

The $id in my test case is "american"

...but... no results.

Does anyone see anything obviously wrong? Appreciated!

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
  • Unfortunately, your query doesn't match your data at all. You can use dot notation for document field queries, but they can't be use to reach into documents in subcollections as your data is currently organized. If you want to query documents in subcollections, you will need to build a path to that subcollection. – Doug Stevenson Nov 14 '20 at 18:29
  • all I want is 'give me all the burger bars in town' and I am not restricted by how it's set up. I had the cuisines in an array but it gave me an error on type, so I'm trying this method. what would you suggest? – BillyParadise Nov 14 '20 at 18:50
  • You're going to have to restructure your data to support the queries you intend to perform. With nosql type databases, modeling can only really happen after you know your queries - the queries will dictate how the data is modeled. – Doug Stevenson Nov 14 '20 at 19:13
  • Yes, Im happy to remodel the database. A decade or two with SQL has left me with serious habits to break! – BillyParadise Nov 15 '20 at 17:01
  • Had to take a week off. Thanks for the detailed reply below. I'll test now and probably give you awesome thumbs ups, checkmarks, and general joy. – BillyParadise Nov 23 '20 at 18:31

1 Answers1

1

Queries on Cloud Firestore operate on a single collection, or a group of collections with the same name. There is no way to have a condition (or otherwise read) data from another collection in a query.

This means you .where('cuisines.$id.exists', isEqualTo: true) can only work if cuisines.$id.exists is present in the restaurant document. The most common way to implement your use-case is to add an array-field servedCuisines to the restaurant document, with the contents being the cuisines the restaurant serves.

`servedCuisines: ["american"]`

You then use an arrayContains operation in the query:

final Query locations = FirebaseFirestore.instance
        .collection('locations')     
        .where("cuisinesServed", arrayContains: id);
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • prefect, thanks! I'm sure I tried such a basic thing last week, but with no results. I may have had a typecasting issue - either way, thanks for your assistance! – BillyParadise Nov 23 '20 at 18:37