我想删除超过两个小时的数据。目前,在客户端,我遍历所有数据并对过时的数据运行删除。当我这样做时,db.on('value')
每次删除某些内容时都会调用该函数。此外,只有在客户端连接时才会删除内容,如果两个客户端同时连接会发生什么?
我在哪里可以设置删除旧数据的东西?我在 JavaScript 创建的每个对象中都有一个时间戳Date.now()
。
我想删除超过两个小时的数据。目前,在客户端,我遍历所有数据并对过时的数据运行删除。当我这样做时,db.on('value')
每次删除某些内容时都会调用该函数。此外,只有在客户端连接时才会删除内容,如果两个客户端同时连接会发生什么?
我在哪里可以设置删除旧数据的东西?我在 JavaScript 创建的每个对象中都有一个时间戳Date.now()
。
Firebase 不支持带有动态参数的查询,例如“两小时前”。但是,它可以对特定值执行查询,例如“after August 14 2015, 7:27:32 AM”。
这意味着,你可以定期运行的代码片段是年长2个多小时的清理项目在那个时候:
var ref = firebase.database().ref('/path/to/items/');
var now = Date.now();
var cutoff = now - 2 * 60 * 60 * 1000;
var old = ref.orderByChild('timestamp').endAt(cutoff).limitToLast(1);
var listener = old.on('child_added', function(snapshot) {
snapshot.ref.remove();
});
正如您会注意到的,我使用child_added
代替value
, 和 I limitToLast(1)
。当我删除每个孩子时,Firebase 将为child_added
新的“最后一个”项目触发一个,直到截止点之后没有更多项目。
更新:如果您想在 Cloud Functions for Firebase 中运行此代码:
exports.deleteOldItems = functions.database.ref('/path/to/items/{pushId}')
.onWrite((change, context) => {
var ref = change.after.ref.parent; // reference to the items
var now = Date.now();
var cutoff = now - 2 * 60 * 60 * 1000;
var oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
return oldItemsQuery.once('value', function(snapshot) {
// create a map with all children that need to be removed
var updates = {};
snapshot.forEach(function(child) {
updates[child.key] = null
});
// execute all updates in one go and return the result to end the function
return ref.update(updates);
});
});
每当在 下写入数据时都会触发此函数/path/to/items
,因此只有在修改数据时才会删除子节点。
此代码现在也可在functions-samples
repo 中找到。
我有一个 http 触发的云函数可以删除节点,具体取决于节点的创建时间和到期日期。
当我向数据库添加一个节点时,它需要两个字段:时间戳以了解其创建时间,以及持续时间以了解优惠何时必须到期。
然后,我有这个 http 触发的云功能:
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
/**
* @function HTTP trigger that, when triggered by a request, checks every message of the database to delete the expired ones.
* @type {HttpsFunction}
*/
exports.removeOldMessages = functions.https.onRequest((req, res) => {
const timeNow = Date.now();
const messagesRef = admin.database().ref('/messages');
messagesRef.once('value', (snapshot) => {
snapshot.forEach((child) => {
if ((Number(child.val()['timestamp']) + Number(child.val()['duration'])) <= timeNow) {
child.ref.set(null);
}
});
});
return res.status(200).end();
});
您可以创建一个 cron 作业,每 X 分钟向该函数的 URL 发出一次请求:https : //cron-job.org/en/
但我更喜欢运行我自己的脚本,每 10 秒发出一个请求:
watch -n10 curl -X GET https://(your-zone)-(your-project-id).cloudfunctions.net/removeOldMessages
在最新版本的 Firebase API 中,ref() 更改为 ref
var ref = new Firebase('https://yours.firebaseio.com/path/to/items/');
var now = Date.now();
var cutoff = now - 2 * 60 * 60 * 1000;
var old = ref.orderByChild('timestamp').endAt(cutoff).limitToLast(1);
var listener = old.on('child_added', function(snapshot) {
snapshot.ref.remove();
});
您可以查看Scheduling Firebase Functions with Cron Jobs。该链接向您展示了如何安排 Firebase 云函数以固定速率运行。在预定的 Firebase 函数中,您可以使用此线程中的其他答案来查询旧数据并将其删除。
如果有人会遇到同样的问题,但在Firestore 中。我做了一个小脚本,首先将文档读取到 console.log,然后从超过 24 小时的集合消息中删除文档。使用https://cron-job.org/en/每 24 小时刷新一次网站,仅此而已。代码如下。
var yesterday = firebase.firestore.Timestamp.now();
yesterday.seconds = yesterday.seconds - (24 * 60 * 60);
console.log("Test");
db.collection("messages").where("date",">",yesterday)
.get().then(function(querySnapshote) {
querySnapshote.forEach(function(doc) {
console.log(doc.id," => ",doc.data());
});
})
.catch(function(error) {
console.log("Error getting documents: ", error);
});
db.collection("messages").where("date","<",yesterday)
.get().then(function(querySnapshote) {
querySnapshote.forEach(element => {
element.ref.delete();
});
})