从 Firebase 获取数据时如何过滤颤动中的项目

时间:2021-02-19 09:00:57

标签: firebase flutter dart google-cloud-firestore

我目前正在使用 FirebaseFirestore.instance.collection('cars').get() 从 firebase 获取与汽车详细信息相关的数据。 我将所有 Car 实例保存在 List<Cars> _cars = []; 使用我在 addCarsToList

中执行的 didChangeDependencies{} 方法
Future<void> addCarsToList({BuildContext context, FilterBy filter}) async {
    var lastDocTracker =
        Provider.of<LastDocumentTracker>(context, listen: false);

    try {
      var dcs = filter != null
          ? await carsCollection.orderBy('dueDate').limit(5).where('readyToRepair', isEqualTo: false).get()
          : await carsCollection.orderBy('dueDate').limit(5).get();

//print(dcs.docs.last.data());

      for (int i = 0; i < dcs.docs.length; i++) {
        Cars carValue = singleCar(dcs, i);

        if (_cars.every((item) => item.carId != carValue.carId)) {
          _cars.add(carValue);
          notifyListeners();
        }
      }
      lastDocTracker.changeLastDocument(dcs.docs.last);
    } catch (e) {
      print(e);
    }
  }

这里我使用 lastDocumentTracer 来跟踪最后一个文档以实现分页。 因此,为了实现分页,我使用滚动控制器并调用 getMore 方法

  Future<void> getMore(
      BuildContext context, QueryDocumentSnapshot lastSnap) async {
    print('getMore called');
    var lastDocTracker =
        Provider.of<LastDocumentTracker>(context, listen: false);
    var dcs = await carsCollection
        .orderBy('dueDate')
        .startAfterDocument(lastSnap)
        .limit(5)
        .get();

    if (dcs.docs.isNotEmpty)
      for (int i = 0; i < dcs.docs.length; i++) {
        Cars carValue = singleCar(dcs, i);

        if (_cars.every((item) => item.carId != carValue.carId)) {
          _cars.add(carValue);
          notifyListeners();
        }
      }
    if (dcs.docs.isNotEmpty) lastDocTracker.changeLastDocument(dcs.docs.last);
    return;
  }

我目前面临的问题是我有三个过滤器(全部、即将推出、准备就绪)。

All 表示来自 firebase 的所有汽车,没有任何过滤器。

即将推出是指未来即将推出的汽车。 (在 Firestore 中保存为 DateTime.millisecondsSinceEpoch )

Ready 表示可以修理的汽车(在 firestore 中保存为 bool) Have a look into the screenshot

我正在尝试使用 where((element) => isReadyToRepair) 过滤汽车列表并使用 setState 但不幸的是,因为我将其限制为来自 Firebase 的 5 个项目,如果没有带有字段 isReadyToRepair = true 的汽车,那么我不能向下滚动并使用滚动控制器调用 getMore,因此它显示为空且未加载任何数据。

伙计们,我需要你们的帮助。请帮我。如果我没有解释清楚,请告诉我。

1 个答案:

答案 0 :(得分:3)

如果您想同时获得 5 个,您需要对数据库进行 3 次不同的查询并使用 where 方法,您有文档 here

您的查询将更像这样:

var dcs = await carsCollection
    .orderBy('dueDate')
    .where('ready', isEqualTo: true)
    .startAfterDocument(lastSnap)
    .limit(5)
    .get();

-- 更新

那是题外话,抱歉了。您需要在 LastDocumentTracker 中创建两个不同的引用。我想您将最后一个文档存储在一个变量中,所以我要做的是为过滤的文档创建一个(或者为您应用的每个过滤器创建一个),并为所有文档创建一个。然后,当您获得文档时,您会根据您应用的过滤器找到正确的变量。为了稍微改进代码维护和优雅,我会使用 addCarsToList 来获得更多和第一次获得它们:

//New addCarsToList
Future<void> addCarsToList(LastDocumentTracker tracker, {FilterBy filter}) async { //Tracker as required and filter as optional
    
    bool hasFilter = filter != null;

    var lastSnap = tracker.getLastSnap(filtered: hasFilter);

    bool isFirst = lastSnap != null;

    var dcs;
        
    try {
      if(hasFilter){
            dcs = isFirst ? await carsCollection.orderBy('dueDate').limit(5).where('readyToRepair', isEqualTo: false).get() : await carsCollection.orderBy('dueDate').startAfterDocument(lastSnap).limit(5).where('readyToRepair', isEqualTo: false).get()
      } else{

        dcs = isFirst ? await carsCollection.orderBy('dueDate').limit(5).get(); : await carsCollection.orderBy('dueDate').startAfterDocument(lastSnap).limit(5).get();
      }

      for (var doc in dcs.docs) {
        Cars carValue = singleCar(doc); // Make it get a single document, what's the point on passing both a list and an index ?

        if (_cars.every((item) => item.carId != carValue.carId)) { //questionable
          _cars.add(carValue);
          notifyListeners();
        }
      }

      lastDocTracker.changeLastDocument(dcs.docs.last, filtered: hasFilter);
    } catch (e) {
      print(e);
    }
  }

我修改了很多东西,如果你不明白什么,请告诉我。在这之后你应该做一些调整,比如:

  • 在跟踪器中为过滤项目添加变量;
  • 在changeLastDocument中添加“filtered”参数并修改右边 基于此参数的变量;
  • 将跟踪器而不是上下文传递给方法(当你传递一个对象时,你传递的是它的引用,而不是副本,所以如果你修改它,你将修改你传递的那个;))
  • 修改 singleCar 方法以接受对象而不是列表和索引