代码之家  ›  专栏  ›  技术社区  ›  user1187968

颤振:Firebase实时数据库orderByChild对查询结果没有影响

  •  0
  • user1187968  · 技术社区  · 5 年前

    我已经这样将数据插入Firebase实时数据库:

    enter image description here

    我这样查询数据库:

    final databaseReference = FirebaseDatabase.instance.reference();
    databaseReference
        .child('orders')
        .orderByChild('date_slug')
        .limitToFirst(pageSize)
        .once()
        .then((snapshot) {
      firstPageItems = snapshot.value;
    
      if (firstPageItems != null) {
        List<dynamic> curretList = [];
        firstPageItems.forEach((orderId, orderData) {
    
          print ("date_slug " + orderData['date_slug'] + "\r\n\r\n\r\n");
          curretList.add(orderData);
        });
    
        _list.addAll(curretList);
        _listController.sink.add(_list);
      }
    });
    

    然而,数据并没有像我预期的那样整理出来。请参见下面的输出。

    I/flutter (17125): date_slug 2020-04-20 15:52:13
    I/flutter (17125): 
    I/flutter (17125): 
    I/flutter (17125): date_slug 2020-04-20 15:52:11
    I/flutter (17125): 
    I/flutter (17125): 
    I/flutter (17125): date_slug 2020-04-20 15:52:10
    I/flutter (17125): 
    I/flutter (17125): 
    I/flutter (17125): date_slug 2020-04-20 15:52:12
    
    0 回复  |  直到 5 年前
        1
  •  11
  •   Frank van Puffelen    3 年前

    你一打电话 firstPageItems = snapshot.value ,您正在将结果转换为地图/字典。字典可以保存结果的键和值,但它没有放置结果相对顺序的位置。

    要保持结果的顺序,您需要观察 onChildAdded :

    var query = databaseReference
        .child('orders')
        .orderByChild('date_slug')
        .limitToFirst(pageSize);
    query.onChildAdded
        .forEach((event) => {
          print(event.snapshot.value)
        });
    

    如果需要知道查询的所有子节点何时都已处理,可以向value事件添加一个额外的侦听器:

    query.once().then((snapshot) {
      print("Done loading all data for query");
    });
    

    添加此附加侦听器不会导致下载额外数据,因为Firebase会在幕后消除重复数据。


    或者,你可以 FirebaseList class 来自FlatterFire图书馆,它使用同样的 从前 另一个呢 onChild... 流来维护索引列表。

    使用此类的示例如下:

    list = FirebaseList(query: query, 
      onChildAdded: (pos, snapshot) {},
      onChildRemoved: (pos, snapshot) {},
      onChildChanged: (pos, snapshot) {},
      onChildMoved: (oldpos, newpos, snapshot) {},
      onValue: (snapshot) {
        for (var i=0; i < this.list.length; i++) {
          print('$i: ${list[i].value}');
        }
      }
    );
    

    正如你所看到的,它使用 onValue 要按顺序在子对象上循环的列表流。这个 从前。。。 方法是必要的 FirebaseList 同学们,但我们在这里没有对他们做任何有意义的事情。


    在最新版本的FlatterFire库中 DataSnapshot 全班现在有一个 children 财产,意味着你可以 最后 做:

    query.onValue((event) {
      event.snapshot.children.forEach((child) {
        print(child.value);
      });
    })