通过映射字段​​在 flutter 中搜索元素

search element in flutter by mapped field

我有一个简单的菜肴集合,对于每一个我都有一个成分列表。

我想搜索所有含有特定配料的菜肴,但如果我写了一种配料,我可以检索到不止一种配料。 想象一下,例如我有 3 个含有油成分的菜肴,但我可以有不同的油(特级初榨油、花生油......)所以当我写 OIL 时,我必须检索所有含有所有类型油的菜肴。

我有一份菜品清单,每道菜的组成如下:

dish_1-->
|       |-->name: name_1
|       |-->ingredients -->
|                         |--> 1 --> 
|                                  |-->id:1
|                                  |-->name: Extra Virgin Oil
|                         |--> 3 --> 
|                                  |-->id:3
|                                  |-->name: Pasta
|
dish_2-->
|       |-->name: name_2
|       |-->ingredients -->
|                         |--> 2 --> 
|                                  |-->id:2
|                                  |-->name: Peanut Oil
|                         |--> 3 --> 
|                                  |-->id:4
|                                  |-->name: Tomato

我使用了模型 - 助手 - 提供者,我的想法是从成分集合中检索所有带有“油”的成分 ID,然后通过这些 ID 进行查询。 在我的 dish_helpers 我写道:

Future<List<DishModel>> searchDishByIngredient({String ingredient}) {
    String searchKey = ingredient[0].toUpperCase() + ingredient.substring(1);
    List<DishModel> dishes = [];
    return _firestore.collection(subcollection).orderBy("name").startAt([searchKey]).endAt(
        [searchKey + '\uf8ff']).get().then((result) {
  for (DocumentSnapshot ingredient in result.docs) {
        _firestore.collection(collection).where("ingredients."+ingredient.id.toString()+".id",isEqualTo: int.parse(ingredient.id) ).get().then((result) {
          for (DocumentSnapshot dish in result.docs) {
            dishes.add(DishModel.fromSnapshot(dish));
            print("Length: " + dishes.length.toString());
          }
        });
      }
      return dishes;
    });
  }

并在盘中提供者

Future searchByIngredient({String ingredientName}) async {
    dishesSearched = await _dishServices.searchDishByIngredient(ingredient: ingredientName);
    notifyListeners();
  }

当我按成分搜索时,我总是得到一个空列表,但在控制台中我得到:“长度:2”。

为了弄明白我错过了什么,我快疯了

谁能帮帮我?

接受其他执行搜索的方式。

谢谢

看起来您 return 是对 collection 的 get 调用,而不是列表本身。我建议编写这样的代码:

Future<List<DishModel>> searchDishByIngredient({String ingredient}) async {
  String searchKey = ingredient[0].toUpperCase() + ingredient.substring(1);
  List<DishModel> dishes = [];

  dynamic result = await _firestore
      .collection(subcollection)
      .orderBy("name")
      .startAt([searchKey]).endAt([searchKey + '\uf8ff']).get();

  for (DocumentSnapshot ingredient in result.docs) {
    dynamic result2 = await _firestore
        .collection(collection)
        .where("ingredients." + ingredient.id.toString() + ".id",
            isEqualTo: int.parse(ingredient.id))
        .get();

    for (DocumentSnapshot dish in result2.docs) {
      dishes.add(DishModel.fromSnapshot(dish));
      print("Length: " + dishes.length.toString());
    }
  }

  return dishes;
}

在您的代码片段中,将执行获取 collection 的异步调用并按照您的解释记录数据,但您不会获得您期望的 List return因为它 return 在 collection.

get 你是 Future

您似乎在 return 填写清单之前正在点菜。这是因为 for 循环中有异步调用 (then()) 并在您 return 洗碗后完成。
解决方案是简单地使用 Future.forEach 并等待它的执行。也不需要 return .then() 回调,因为你可以等待它。

Future<List<DishModel>> searchDishByIngredient({String ingredient}) async {
    String searchKey = ingredient[0].toUpperCase() + ingredient.substring(1);
    List<DishModel> dishes = [];
    var result = await _firestore.collection(subcollection).orderBy("name").startAt([searchKey]).endAt([searchKey + '\uf8ff']).get();    
    await Future.forEach(result.docs, (DocumentSnapshot ingredient) {
      _firestore.collection(collection).where("ingredients." + ingredient.id.toString() + ".id",isEqualTo: int.parse(ingredient.id)).get().then((result) {
        for (DocumentSnapshot dish in result.docs) {
          dishes.add(DishModel.fromSnapshot(dish));
          print("Length: " + dishes.length.toString());
        }
      });
    });
    return dishes;
  }