【问题标题】:Is There another way apart from if else statement for Multi Filter Search Flutter Firebase?除了多过滤器搜索 Flutter Firebase 的 if else 语句之外,还有其他方法吗?
【发布时间】:2026-02-19 16:50:01
【问题描述】:

我正在尝试在 Zillow 应用程序中实现多过滤器功能。我正在使用 Flutter、Firebase 和 Provider Package。

用户可以按价格范围、区域范围、城市、邮政编码、浴室、卧室和便利设施进行过滤。 用户可以选择任何过滤器组合。 当使用组合计算时,我最终得到了 127 个组合?

  1. 是否有任何有效的方法来获取每个组合的查询?
  2. 对于大量查询,Looping 或 Switch 语句是否是良好的代码实践?

 Future<void> getApartmentbyCityPrice(PersonalHomeList personalApartmentList,String city,double 
  maxPrice, double minPrice) async {
     if (city == "Any" && maxPrice != null && minPrice != null) {
         QuerySnapshot snapshot = await FirebaseFirestore.instance.collection('apartments'). 
          where("price",isGreaterThanOrEqualTo: minPrice, isLessThanOrEqualTo: maxPrice).get();
            List<PersonalApartment> _loadedPersonalApartment = [];
            snapshot.docChanges.forEach((result) {
            PersonalApartment personalApartment = new PersonalApartment(
            id: result.doc['id'],
            userId: result.doc['userId'],
            amenities: result.doc['amenities'],
            area: result.doc['area'],
            bathroom: result.doc['bathroom'],
            bedroom: result.doc['bedroom'],
            city: result.doc['city'],
            createdAt: result.doc['createdAt'],
            description: result.doc['description'],
            imageUrl: result.doc['imageUrl'],
            price: result.doc['price'],
            streetName: result.doc['streetName'],
            updatedAt: result.doc['updatedAt'],
            zipcode: result.doc['zipcode'],
          );
      _loadedPersonalApartment.add(personalApartment);
    });
   personalApartmentList.apartmentListByCity = _loadedPersonalApartment;
   } else if (city.isNotEmpty && city != "Any" && maxPrice == 0.0 && minPrice == 0.0) {
         QuerySnapshot snapshot = await FirebaseFirestore.instance.collection('apartments') 
         .where("city", isEqualTo: city).get();
          List<PersonalApartment> _loadedPersonalApartment = [];
          snapshot.docChanges.forEach((result) {
          PersonalApartment personalApartment = new PersonalApartment(
          id: result.doc['id'],
          userId: result.doc['userId'],
          amenities: result.doc['amenities'],
          area: result.doc['area'],
          bathroom: result.doc['bathroom'],
          bedroom: result.doc['bedroom'],
          city: result.doc['city'],
          createdAt: result.doc['createdAt'],
          description: result.doc['description'],
          imageUrl: result.doc['imageUrl'],
          price: result.doc['price'],
          streetName: result.doc['streetName'],
          updatedAt: result.doc['updatedAt'],
          zipcode: result.doc['zipcode'],
        );
        _loadedPersonalApartment.add(personalApartment);
     });
     personalApartmentList.apartmentListByCity = _loadedPersonalApartment;
   } else {
    QuerySnapshot snapshot = await FirebaseFirestore.instance.collection('apartments').where("city", 
    isEqualTo: city).where("price",isGreaterThanOrEqualTo: minPrice, isLessThanOrEqualTo: maxPrice)
    .get();
     List<PersonalApartment> _loadedPersonalApartment = [];
     snapshot.docChanges.forEach((result) {
     PersonalApartment personalApartment = new PersonalApartment(
       id: result.doc['id'],
       userId: result.doc['userId'],
       amenities: result.doc['amenities'],
       area: result.doc['area'],
       bathroom: result.doc['bathroom'],
       bedroom: result.doc['bedroom'],
       city: result.doc['city'],
       createdAt: result.doc['createdAt'],
       description: result.doc['description'],
       imageUrl: result.doc['imageUrl'],
       price: result.doc['price'],
       streetName: result.doc['streetName'],
       updatedAt: result.doc['updatedAt'],
       zipcode: result.doc['zipcode'],
      );
      _loadedPersonalApartment.add(personalApartment);
      });
       personalApartmentList.apartmentListByCity = _loadedPersonalApartment;
  }   
}

示例查询示例

  QuerySnapshot snapshot = await FirebaseFirestore.instance.collection('apartments').where("price", 
   isGreaterThanOrEqualTo: minPrice, isLessThanOrEqualTo: maxPrice).get();
  QuerySnapshot snapshot = await FirebaseFirestore.instance.collection('apartments').where("area", 
   isGreaterThanOrEqualTo: areaRange.start, isLessThanOrEqualTo: areaRange.end).get();
  QuerySnapshot snapshot = await FirebaseFirestore.instance.collection('apartments').
    where("bathroom", arrayContainsAny: bathroom).get();
  QuerySnapshot snapshot = await FirebaseFirestore.instance.collection('apartments').where("bedroom", 
    arrayContainsAny: bedroom).get();

过滤屏幕

[![过滤屏幕] [![过滤屏幕]

【问题讨论】:

    标签: firebase flutter dart google-cloud-firestore


    【解决方案1】:

    我想你正在使用 Firestore。

    现在,您要根据以下条件在 Firestore 中查询公寓:

    • 价值观
      • 城市
      • 邮政编码
    • 范围
      • 价格范围
      • 区域范围
      • 浴室
      • 卧室
    • 数组
      • 设施

    你要做的是使用Compound Queries

    Query query = FirebaseFirestore.instance.collection('apartments');
    if (city.isNotEmpty && city != "Any") {
      query = query.where("city", isEqualTo: city)
    }
    if (zipCode.isNotEmpty && zipCode != "Any") {
      query = query.where("zipCode", isEqualTo: zipCode)
    }
    ...
    QuerySnapshot snapshot = await query.get();
    List<PersonalApartment> apartments = snapshot.docChanges.map(
      (result) => PersonalApartment.fromFirestore(result.doc),
    );
    

    您的主要问题是 Compound Queries 在 Firestore 中非常有限。限制之一是您不能在多个字段上组合范围过滤器。

    因此,您只能在查询中执行一个范围过滤器,而在应用程序中执行另一个客户端。也许您可以确定范围过滤器的顺序,从最严格(将返回最小的一组公寓)到最一般的过滤器。

    Query _buildQuery() {
      Query query = FirebaseFirestore.instance.collection('apartments');
    
      // SIMPLE QUERIES
      if (city.isNotEmpty && city != "Any") {
        query = query.where("city", isEqualTo: city)
      }
      if (zipCode.isNotEmpty && zipCode != "Any") {
        query = query.where("zipCode", isEqualTo: zipCode)
      }
    
      // RANGE QUERIES
      if (minPrice != null || maxPrice != null) {
        if (minPrice != null) {
          query = query.where("price", ">=", minPrice);
        }
        if (maxPrice != null) {
          query = query.where("price", "<=", maxPrice);
        }
        return query;
      }
      if (minArea != null || maxArea != null) {
        ...
        return query;
      }
      if (...) { ... }
      ...
      return query;
    }
    
    ...
    
    QuerySnapshot snapshot = await _buildQuery().get();
    List<PersonalApartment> apartments = snapshot.docChanges.map(
      (result) => PersonalApartment.fromFirestore(result.doc),
    );
    apartments = apartments.where((apartment) { /* perform remaining filters clmient-side */ })
    

    【讨论】:

    • 客户端查询是个好方法吗?同样对于很多不同的组合,if else 语句或 Switch 语句是大量查询的良好代码实践吗?
    • 查询客户端是否是个好方法?我认为没有其他方法可以执行多个范围查询。我很想知道你是否找到办法。 这是一种好的做法吗? 您或许可以改进这一点。检查我更新的答案。通过使用_buildQuery()方法,我删除了 if else if else if else if else if else if else。