Node.js 使用Firebase云函数删除旧数据
我需要定期从Firebase中删除旧数据。我找到了,但没能使它工作 终端告诉我Node.js 使用Firebase云函数删除旧数据,node.js,firebase,firebase-realtime-database,google-cloud-functions,Node.js,Firebase,Firebase Realtime Database,Google Cloud Functions,我需要定期从Firebase中删除旧数据。我找到了,但没能使它工作 终端告诉我功能[deleteOldItems(us-central1)]:更新操作成功。但数据未被删除 这就是我所做的: const functions = require('firebase-functions'); exports.deleteOldItems = functions.database.ref('/nodeThatContainsDataToBeDeleted') .onWrite((change, con
功能[deleteOldItems(us-central1)]:更新操作成功。
但数据未被删除
这就是我所做的:
const functions = require('firebase-functions');
exports.deleteOldItems = functions.database.ref('/nodeThatContainsDataToBeDeleted')
.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);
});
});
时间戳是639915248.124176
(来自Swift)
数据库结构:
root : {
"nodeThatContainsDataToBeDeleted" : {
"-r5tyfX9FGC0glhgf78Ia" : {
"company" : "CompanyCo",
"name" : "Sam",
"phone" : "1212",
"imageURL" : "https://firebasestorage.googleapis.com/imageurl",
"timestamp" : 6.39915248124176E8
}
},
}
当您在后台触发的云函数中执行异步操作时(在您的例子中是once()
和update()
方法),您必须返回一个承诺,以这种方式,云函数将等待此承诺解析以终止。标题为“学习JavaScript承诺”的三篇文章中有更多的信息(第2部分和第3部分特别关注后台触发的云函数,但之前的第1部分确实值得一看)
通过执行oldItemsQuery.once('value',function(snapshot){…})
实际上使用的是该方法的回调版本
为了正确链接不同的承诺并在回调中返回此链,您需要使用承诺版本,如下所示:
exports.deleteOldItems = functions.database.ref('/nodeThatContainsDataToBeDeleted')
.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')
.then(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);
});
});
这个答案建立在他的基础上
JavaScript和Firebase SDK自2015年以来已经取得了长足的进步,因此在复制/使用StackOverflow上的旧代码示例时要小心这一点。网站还链接到最新的具有现代特色的网站
正如Renaud所述,您需要切换到专门使用Promise
版本的once()
侦听器,而不是使用回调。虽然您的代码确实按预期返回了Promise
,但当前回调没有正确插入Promise
链,这意味着您的云函数没有等待回调中的代码完成。这本书是在2015年写的,在那里它曾经起作用,但现在已经不是这样了
这些线路:
return oldItemsQuery.once('value', function(snapshot) {
/* ... use snapshot ... */
});
应该是:
return oldItemsQuery.once('value')
.then((snapshot) => {
/* ... use snapshot ... */
});
functions.database.ref('/nodeThatContainsDataToBeDeleted/{pushId}') // fetches only the entry that changed
或:
接下来,您已将onWrite
侦听器配置为侦听/nodeThatContainsDataToBeDeleted
上的更改。虽然这样做有效,但效率极低。对于在/nodethattcontainsdatatobedeleted
下的某个点上数据库中的每个小更改(例如/nodethattcontainsdatabedeleted/somePushId/someBoolean=true
),函数将下载该节点下嵌套的所有数据。对于此节点上的几个条目,这是无关紧要的,但当您接近数千个条目时,您可能会读取许多兆字节的数据
如果查看链接的示例,侦听器将附加到/path/to/items/{pushId}
(单个书面条目),而不是/path/to/items
(所有条目)。{pushId}
过去是一个捕获路径最后一部分的过程(如-r5tyfX9FGC0glhgf78Ia
)
这一行:
functions.database.ref('/nodeThatContainsDataToBeDeleted') // fetches all entries
应该是:
return oldItemsQuery.once('value')
.then((snapshot) => {
/* ... use snapshot ... */
});
functions.database.ref('/nodeThatContainsDataToBeDeleted/{pushId}') // fetches only the entry that changed
注意:此函数的一个“错误”是它会重新触发自身。对于它删除的每个条目,deleteOldItems
将再次触发。您可能希望使用.onCreate()
或.onUpdate()
而不是.onWrite()
-有关详细信息,请参阅
结合这些变化(在撰写本文时建立):
该终端消息只是说明名为deleteOldItems
的云函数已成功部署。它与您的代码无关。请在问题中包括您的数据库结构。@samthecodingman包括数据库结构NodeThatContainesDataObeDeleted
直接位于根目录下,因此您所指的问题是:“每当在/path/to/items下写入数据时,就会触发此函数,因此只有在修改数据时才会删除子节点。”您是如何触发此函数的?