我想删除两个小时以前的任何数据。目前,在客户端,我遍历所有数据,并对任何较旧的数据运行删除。当我这样做时,每次删除某些内容时都会调用db.on(' value')函数。此外,只有在客户端连接时才会删除内容,如果两个客户端同时连接会发生什么?
我可以在哪里设置删除旧数据的内容?我在JavaScript Date.now()创建的每个对象中都有一个时间戳。
答案 0 :(得分:39)
Firebase不支持使用动态参数的查询,例如“两小时前”。然而,可以执行特定值的查询,例如“2015年8月14日之后,上午7:27:32”。
这意味着您可以定期运行一段代码来清理当时超过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
,而我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。
答案 1 :(得分:6)
在最新版本的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();
});
答案 2 :(得分:3)
您可以查看Scheduling Firebase Functions with Cron Jobs。该链接显示如何安排Firebase云功能以固定费率运行。在计划的Firebase功能中,您可以使用此线程中的其他答案来查询旧数据并将其删除。
答案 3 :(得分:2)
我有一个http触发的云功能,该功能会删除节点,具体取决于节点的创建时间和到期日期。
当我将一个节点添加到数据库时,它需要两个字段:时间戳以了解其创建时间,以及 duration 以了解要约何时到期。 / p>
然后,我有这个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
答案 4 :(得分:1)
如果有人也会遇到相同的问题,但是在 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();
});
})