Home > Software design >  Flutter Firestore only return user overview ListTile when field contains specific words
Flutter Firestore only return user overview ListTile when field contains specific words

Time:03-10

I am listing users in a CustomScrollView/SliversList,ListTiles. I have a String field in my firestore and only want to return ListTile of a user, where his String field contains specific words (more than 2). For example, the users fields contain: "Apples, Ice, Bananas, Soup, Peaches, e.g...." and i want to list all users which have apples and bananas inside the field. how can i achieve this?

CodePudding user response:

The only way to do it at the moment (with the way you have it set up) is actually pulling the value and doing a string "contains" or splitting the string into an array and check whether the value is within that array, otherwise I'd advise to refactor that field and make it into an array, that way you can perform a native arrayContainsAny against your field.

For you it will look like this (with your current implementation):

// ... after pulling all users' documents
// let's say your field is called 'foodField':

var criteria = 'Banana';
var fieldContent = doc.data()['foodField'];

// you can either do this:
if (fieldContent.toLowerCase().contains(criteria.toLowerCase())) {
  // ...
}

// or you can tokenize it depending on your purposes...
var foodTokens = fieldContent.split(',').map((f) => f.toLowerCase());
if (foodTokens.contains(criteria.toLowerCase()) {
 // ... 
}

If your Firestore field was an array type, then you could've just done that, while querying:

FirebaseFirestore.instance.collection('users').where('foodField', arrayContainsAny: ['Banana', 'Apples'])

Which then would give you only the users whose foodField contain that value.

CodePudding user response:

As you can see from previous questions on querying where text contains a substring, Firestore does not currently support such text searches. The typical solutions are to either perform part of your filtering in your application code as Roman answered, or to integrate a third-party full-text search solution.


In your specific case though, your string seems to be a list of words, so I'd recommend considering to change your data model to an array of the individual values in there:

"foodFields": ["Apples", "Ice", "Banana", "Soup", "Peaches"]

You can then use array field operators in the query.

While there is no array-contains-all operator, using array-contains you can at least filter on one value in the database, and with array-contains-any you can do on OR like condition.


Another data model would be to store the individual values in a map field with value true for each of them:

"foodFields": {
  "Apples": true,
  "Ice": true,
  "Banana": true,
  "Soup": true,
  "Peaches": true
}

With such a structure you can perform an AND like query with:

collectionRef
   .where('foodFields.Apples', isEqualTo: true)
   .where('foodFields.Bananas', isEqualTo: true)
  • Related