按desc排序的时间范围内的Firebase查询值 [英] Firebase query value in time range ordered by desc
问题描述
我的目标:我想从按喜欢(降序)排序的无限集合中检索项目.我还想通过日期和结果计数来限制这些结果,例如前10名.
My goal: I want to retrieve items from an infinite collection ordered by likes (descending). I also want to limit these results by date and result count, e.g. top 10.
我无法适当地管理此案件.到目前为止,这是我得到的结果,但是我只希望获得前10个结果,并且缺少此限制.如果我在查询中放置 limit()
,则不会得到正确的结果.
Im not able to manage this case in a nice way propably. This is what I got so far, but I want only the top 10 results and this limitation is missing. If i place a limit()
inside the query I dont get the correct results.
Timestamp get timeLimit {
final limit = DateTime.now().subtract(const Duration(days: 30));
return Timestamp.fromDate(limit);
}
QuerySnapshot snapshot =
await FirebaseFirestore.instance
.collection('data')
.where('date', isGreaterThanOrEqualTo: timeLimit)
.orderBy('date', descending: true)
.get();
snapshot.docs.forEach((document) {
Data data = Data.fromJson(document.data());
resultList.add(data);
resultList.sort((a, b) => b.likes.compareTo(a.likes));
});
推荐答案
您正在达到Cloud Firestore的限制.如果您有一个具有范围比较的过滤器(<,< =,>,> =),则您的第一次排序必须在同一字段上.[参考:https://cloud.google.com/firestore/docs/query-data/order-limit-data]
You are hitting a limit of Cloud Firestore. If you have a filter with a range comparison (<, <=, >, >=), your first ordering must be on the same field. [Ref: https://cloud.google.com/firestore/docs/query-data/order-limit-data]
在您的情况下,第二个orderBy(在 likes
上)仅在完全相同的 date
的组内有效,这将毫无用处.
In your case, the second orderBy (on likes
) will have an effect only within groups of exactly the same date
, which will be pretty useless.
如果您的目标是跟踪每日/每周/每月的TOP 10 ,则可能应该在Firestore中维护该列表,而不是为每个访问者计算列表.
If your goal is to keep track of the daily / weekly / monthly TOP 10, you should probably maintain that list in Firestore instead of computing the lists for each visitor.
您可以让每个[要定义的持续时间]都运行一个Cloud Function,以重置TOP 10列表.
You could have a Cloud Function running every [duration to be defined] to reset the TOP 10 lists.
这需要付出一定的代价,但是 read
操作对于每个访问者来说都会便宜得多.
This comes at a cost but the read
operations will be dramatically cheaper for each visitor.
这样的函数可以写成:
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.firestore();
exports.computeTopTenLists = functions.pubsub.schedule('every 2 hours').onRun((context) => {
var millisecondsInOneDay = 24 * 60 * 60 * 1000;
var dailyStart = new Date(Date.now() - millisecondsInOneDay);
var weeklyStart = new Date(Date.now() - 7 * millisecondsInOneDay);
var monthlyStart = new Date(Date.now() - 30 * millisecondsInOneDay);
date.setDate(date.getDate() - 7);
// Top 10 list (sorted by likes, descending)
var dailyTopTen = [];
var weeklyTopTen = [];
var monthlyTopTen = [];
db.collection('data').where("date", ">=", monthlyStart ).get().then((querySnapshot) => {
[
{ list: dailyTopTen, start: dailyStart },
{ list: weeklyTopTen, start: weeklyStart },
{ list: monthlyTopTen, start: monthlyStart },
].forEach((curr) => {
curr.list.push(querySnapshot[0].data());
querySnapshot.slice(1).forEach((doc) => {
var data = doc.data();
data['id'] = doc.id;
if (data['date'] > curr.start && data['likes'] > curr.list[curr.list.length-1]) {
curr.list.push(data);
curr.list.sort((a, b) => (a.likes > b.likes ? -1 : 1));
curr.list = curr.list.slice(0, 10);
}
});
});
})
db.collection('top-ten').document('lists').set({
daily: dailyTopTen.map(data => ({id: data['id'], title: data['title']})),
weekly: weeklyTopTen.map(data => ({id: data['id'], title: data['title']})),
monthlyly: monthlyTopTen.map(data => ({id: data['id'], title: data['title']})),
});
return null;
});
只需阅读一份文档,您将获得前三名的前三名列表.
You would get the three Top 10 lists with just one document read.
这篇关于按desc排序的时间范围内的Firebase查询值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!