flutterfirebasegoogle-cloud-firestoresearchbarsearchfiltercollection

How to search by multiple filters with Firebase in my Flutter app?


I made a search bar for my Flutter App and put a filtering button next to this search bar.

When the user clicks on this filtering button, a 'bottom sheet' will open on the screen and user can select multiple filter (refer image) and apply

I want only the ads that match those filters to be shown on the screen. On the bottom sheet that opens, the user should be able to view the list of ads with the fields in the image (type, age, sex, gender, etc.). It would be easy if I used only type as a range filter option and paging. But there are multiple range filters and I don't know how to do that.

How can I combine these multiple queries? For the user experience, I want the user to quickly find listings that match the criteria they have in mind using multiple filters.

enter image description here

My service class named PetAdoptionService

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:my_pet_app/core/models/animals/pet_adoption_model.dart';
import 'package:my_pet_app/core/services/animals/pet_service.dart';

class PetAdoptionService extends PetService<PetAdoption> {
  final CollectionReference _petsRef =
      FirebaseFirestore.instance.collection('petAdoptions');

  Future<List<PetAdoption>> getPetsByName(String name) async {
    final querySnapshot = await _petsRef.get();
    final pets = <PetAdoption>[];

    for (final doc in querySnapshot.docs) {
      final data = doc.data()! as Map<String, dynamic>;
      final petName = data['name'] as String;

      if (petName.toLowerCase().contains(name.toLowerCase())) {
        pets.add(PetAdoption.fromMap(data));
      }
    }
    return pets;
  }

  // The function that will search with more than one query should be defined here.
}


Solution

  • I managed to solve my problem. Since I think that other friends will have a similar problem with me in the future, I have given the correct code below for the benefit of these friends. I hope it will be useful to everyone.

    class PetAdoptionService extends PetService<PetAdoption> {
      final CollectionReference _petsRef =
          FirebaseFirestore.instance.collection('petAdoptions');
    
      // Function that allows a single query
      Future<List<PetAdoption>> getPetsByName(String name) async {
        final querySnapshot = await _petsRef.get();
        final pets = <PetAdoption>[];
    
        for (final doc in querySnapshot.docs) {
          final data = doc.data()! as Map<String, dynamic>;
          final petName = data['name'] as String;
    
          if (petName.toLowerCase().contains(name.toLowerCase())) {
            pets.add(PetAdoption.fromMap(data));
          }
        }
        return pets;
      }
    
      // Function that allows multiple queries
      Future<List<PetAdoption>> getFilteredPets({
        String? type,
        List<String>? breeds,
        String? gender,
        bool? isVaccinated,
        bool? isNeutered,
        String? city,
        String? district,
      }) async {
        Query query = _petsRef;
    
        if (type != null) {
          query = query.where('type', isEqualTo: type);
        }
        if (breeds != null && breeds.isNotEmpty) {
          query = query.where('breed', whereIn: breeds);
        }
        if (gender != null) {
          query = query.where('gender', isEqualTo: gender);
        }
        if (isVaccinated != null) {
          query = query.where('isVaccinated', isEqualTo: isVaccinated);
        }
        if (isNeutered != null) {
          query = query.where('isNeutered', isEqualTo: isNeutered);
        }
        if (city != null) {
          query = query.where('city', isEqualTo: city);
        }
        if (district != null) {
          query = query.where('district', isEqualTo: district);
        }
    
        final querySnapshot = await query.get();
        return querySnapshot.docs
            .map((doc) => PetAdoption.fromMap(doc.data() as Map<String, dynamic>))
            .toList();
      }
    }