flutter - 从 firebase 实时数据库获取数据切片,按喜欢降序排序以进行分页
flutter - get slices of data from firebase realtime database, sorted by descending likes for pagination
我在 firebase 实时数据库中有一份导师名单。而且他们每个人都有 'numFav' 表示有多少用户喜欢他。
在我的导师列表页面,我想按降序'numFav'的顺序显示已注册的导师。同时,我想分页
所以我编写了初始获取和加载更多代码。
Future<List<MentorModel>> initialMentorFuture(int num) {
final future = _database.orderByChild('numFav').limitToLast(num).once().then((snapshot) {
List<MentorModel> _mentorList = [];
Map<String, dynamic>.from(snapshot.value).forEach((key, value) => _mentorList.insert(0, MentorModel.fromRTDB(key, value)));
return _mentorList;
});
return future;
}
Future<List<MentorModel>> moreMentorFuture(int num, int startAtValue) {
final future = _database.orderByChild('numFav').startAt(startAtValue).limitToLast(num).once().then((snapshot) {
List<MentorModel> _mentorList = [];
Map<String, dynamic>.from(snapshot.value).forEach((key, value) => _mentorList.insert(0, MentorModel.fromRTDB(key, value)));
return _mentorList;
});
return future;
}
initialMentorFuture 按预期工作。 moreMentorFuture 没有。我有两个问题。
我使用的是降序,但是 limitToLast 和 startAt 似乎相互矛盾。
可以有很多导师具有相同的'numFav'。例如,如果第一页中的最后一位导师的 numFav 为 10,我不能只在 moreMentorFuture 中说 startAt(10) 因为可能还有其他导师的 numFav 为 10 而没有显示在第一页中。
我很确定我不是唯一一个尝试按喜欢的数量对列表进行排序的人。有人知道如何解决这个问题吗?
已编辑
还有一个问题:分页真的能节省加载时间吗?当我调用 .orderByChild('numFav').limitToLast(10)
时,实际从服务器下载了多少数据?如果我调用 orderByChild()
它会下载整个数据集进行排序吗?如果是这样,分页有什么意义?
Firebase 实时数据库始终returns 以升序排列结果。如果您想按降序显示它们,则需要在您的应用程序代码中反转结果。
如果你想要倒数第二页的结果,你需要使用 endAt
而不是 startAt
:
_database.orderByChild('numFav').endAt(endAtValue, key: endAtKey).limitToLast(num)
如果不能保证您的 endAtValue
是唯一的(正如名称 numFav
所暗示的那样),您还需要保留 key要锚定的节点,以消除具有相同 numFav
值的节点之间的歧义。
Firebase 去年向实时数据库 API 添加了 startAfter
/endBefore
方法,因此您可能需要考虑使用这些方法来排除 first/last 项next/previous 结果页。
对命名 属性(如 numFav
)的查询要求您在规则中 define an index 才能在服务器上执行。在规则中定义索引后,查询将在服务器上执行。
我在 firebase 实时数据库中有一份导师名单。而且他们每个人都有 'numFav' 表示有多少用户喜欢他。
在我的导师列表页面,我想按降序'numFav'的顺序显示已注册的导师。同时,我想分页
所以我编写了初始获取和加载更多代码。
Future<List<MentorModel>> initialMentorFuture(int num) {
final future = _database.orderByChild('numFav').limitToLast(num).once().then((snapshot) {
List<MentorModel> _mentorList = [];
Map<String, dynamic>.from(snapshot.value).forEach((key, value) => _mentorList.insert(0, MentorModel.fromRTDB(key, value)));
return _mentorList;
});
return future;
}
Future<List<MentorModel>> moreMentorFuture(int num, int startAtValue) {
final future = _database.orderByChild('numFav').startAt(startAtValue).limitToLast(num).once().then((snapshot) {
List<MentorModel> _mentorList = [];
Map<String, dynamic>.from(snapshot.value).forEach((key, value) => _mentorList.insert(0, MentorModel.fromRTDB(key, value)));
return _mentorList;
});
return future;
}
initialMentorFuture 按预期工作。 moreMentorFuture 没有。我有两个问题。
我使用的是降序,但是 limitToLast 和 startAt 似乎相互矛盾。
可以有很多导师具有相同的'numFav'。例如,如果第一页中的最后一位导师的 numFav 为 10,我不能只在 moreMentorFuture 中说 startAt(10) 因为可能还有其他导师的 numFav 为 10 而没有显示在第一页中。
我很确定我不是唯一一个尝试按喜欢的数量对列表进行排序的人。有人知道如何解决这个问题吗?
已编辑
还有一个问题:分页真的能节省加载时间吗?当我调用 .orderByChild('numFav').limitToLast(10)
时,实际从服务器下载了多少数据?如果我调用 orderByChild()
它会下载整个数据集进行排序吗?如果是这样,分页有什么意义?
Firebase 实时数据库始终returns 以升序排列结果。如果您想按降序显示它们,则需要在您的应用程序代码中反转结果。
如果你想要倒数第二页的结果,你需要使用 endAt
而不是 startAt
:
_database.orderByChild('numFav').endAt(endAtValue, key: endAtKey).limitToLast(num)
如果不能保证您的 endAtValue
是唯一的(正如名称 numFav
所暗示的那样),您还需要保留 key要锚定的节点,以消除具有相同 numFav
值的节点之间的歧义。
Firebase 去年向实时数据库 API 添加了 startAfter
/endBefore
方法,因此您可能需要考虑使用这些方法来排除 first/last 项next/previous 结果页。
对命名 属性(如 numFav
)的查询要求您在规则中 define an index 才能在服务器上执行。在规则中定义索引后,查询将在服务器上执行。