关于在 firebase firestore 中存储统计信息的建议
Advice on storing statistics in firebase firestore
在 firestore 中,我有包含字段、日期和样本计数的文档。
我想每周汇总一次按日期分组的统计数据,即所有相同日期的样本计数应该相加。
那么出于历史原因,我想将其存储在统计集合中。
我不确定我是否应该将结果存储在地图字段中,或者使用日期作为归档编号并使用 specimenCount 作为值。
最重要的是存储它以便于阅读历史记录。
使用日期作为文档 ID,使用样本计数作为值。
因此,对于今天 (28-08-2021) 添加的文档,您可以这样添加它
Future<void> storeAnalytics(dynamic data) async {
await FirebaseFirestore.instance.collection("analytics").doc(data['id']).set(
{'value': FieldValue.increment(data['value']), 'date': data['date']},
SetOptions(merge: true));
// I used fieldValue.increment incase you have multiple data for 1 day.
// SetOptions(merge: true), will prevent overwriting data if it already exists
// I added date to the document incase in the future you want to fetch
// between a particular date range (eg. data for the year 2021). Here you can
// just use a where query.
}
// call the above function like this
// you can create a function that returns date (without hypen or slash)
// from regular date and for use as doc id
await storeAnalytics({'id': '28082021', 'value': 'xxx', 'date': 'put in date'});
// In the future, if you want the data, you can call it like this
Future<dynamic> getAnalytics(DateTime start, DateTime end) async {
await FirebaseFirestore.instance
.collection('analytics/')
.orderBy('date', descending: true)
.where('date', isGreaterThanOrEqualTo: start)
.where('date', isLessThan: end).get();
}
在设备上执行此操作毫无意义,而是创建一个云函数来处理此操作。 Javascript 模板如下。
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const db = admin.firestore();
exports.onCreate = functions.firestore
.document("/path-to-document/")
.onCreate((snap, context) => {
const value = snap.data();
const specimentCount = value.value;
const timestamp = value.date;
const date = timestampToDate(timestamp);
const id = timestampToDayId(timestamp);
return db.doc("analytics/" + id)
.set(
{ data: admin.firestore.FieldValue.increment(specimentCount), date },
{ merge: true },
);
});
// if your document can be updated and deleted, you can add a listeners for
// that.
/**
* Returns javascript date (YYYYMMDD) from firebase timestamp.
* @param {timestamp} timestamp The firebase timestamp.
* @return {Date} The javascript date.
*/
function timestampToDate(timestamp) {
const date = timestamp.toDate();
date.setHours(0);
date.setMilliseconds(0);
date.setMinutes(0);
date.setSeconds(0);
return date;
}
/**
* Returns full id from firebase timestamp.
* @param {timestamp} timestamp The firebase timestamp.
* @return {String} The id.
*/
function timestampToDayId(timestamp) {
const date = timestamp.toDate();
let day = date.getDate();
if (day < 10) day = "0" + day;
let month = date.getMonth() + 1;
if (month < 10) month = "0" + month;
return date.getFullYear() + "" + month + "" + day;
}
使用云函数的一个优势是您可以使用 firestore 规则限制分析收集的写入。只允许读取(云函数不需要被授予 firestore 访问权限)。另一个好处是这个任务不会占用设备资源。
在 firestore 中,我有包含字段、日期和样本计数的文档。
我想每周汇总一次按日期分组的统计数据,即所有相同日期的样本计数应该相加。
那么出于历史原因,我想将其存储在统计集合中。
我不确定我是否应该将结果存储在地图字段中,或者使用日期作为归档编号并使用 specimenCount 作为值。
最重要的是存储它以便于阅读历史记录。
使用日期作为文档 ID,使用样本计数作为值。 因此,对于今天 (28-08-2021) 添加的文档,您可以这样添加它
Future<void> storeAnalytics(dynamic data) async {
await FirebaseFirestore.instance.collection("analytics").doc(data['id']).set(
{'value': FieldValue.increment(data['value']), 'date': data['date']},
SetOptions(merge: true));
// I used fieldValue.increment incase you have multiple data for 1 day.
// SetOptions(merge: true), will prevent overwriting data if it already exists
// I added date to the document incase in the future you want to fetch
// between a particular date range (eg. data for the year 2021). Here you can
// just use a where query.
}
// call the above function like this
// you can create a function that returns date (without hypen or slash)
// from regular date and for use as doc id
await storeAnalytics({'id': '28082021', 'value': 'xxx', 'date': 'put in date'});
// In the future, if you want the data, you can call it like this
Future<dynamic> getAnalytics(DateTime start, DateTime end) async {
await FirebaseFirestore.instance
.collection('analytics/')
.orderBy('date', descending: true)
.where('date', isGreaterThanOrEqualTo: start)
.where('date', isLessThan: end).get();
}
在设备上执行此操作毫无意义,而是创建一个云函数来处理此操作。 Javascript 模板如下。
const functions = require("firebase-functions");
const admin = require("firebase-admin");
const db = admin.firestore();
exports.onCreate = functions.firestore
.document("/path-to-document/")
.onCreate((snap, context) => {
const value = snap.data();
const specimentCount = value.value;
const timestamp = value.date;
const date = timestampToDate(timestamp);
const id = timestampToDayId(timestamp);
return db.doc("analytics/" + id)
.set(
{ data: admin.firestore.FieldValue.increment(specimentCount), date },
{ merge: true },
);
});
// if your document can be updated and deleted, you can add a listeners for
// that.
/**
* Returns javascript date (YYYYMMDD) from firebase timestamp.
* @param {timestamp} timestamp The firebase timestamp.
* @return {Date} The javascript date.
*/
function timestampToDate(timestamp) {
const date = timestamp.toDate();
date.setHours(0);
date.setMilliseconds(0);
date.setMinutes(0);
date.setSeconds(0);
return date;
}
/**
* Returns full id from firebase timestamp.
* @param {timestamp} timestamp The firebase timestamp.
* @return {String} The id.
*/
function timestampToDayId(timestamp) {
const date = timestamp.toDate();
let day = date.getDate();
if (day < 10) day = "0" + day;
let month = date.getMonth() + 1;
if (month < 10) month = "0" + month;
return date.getFullYear() + "" + month + "" + day;
}
使用云函数的一个优势是您可以使用 firestore 规则限制分析收集的写入。只允许读取(云函数不需要被授予 firestore 访问权限)。另一个好处是这个任务不会占用设备资源。