我的应用程序有一个简单的云功能,可以跟踪创建/更新的时间戳。它看起来像这样:
NOT DEFERRED
只要我上传此功能并在列表中创建/修改对象,它就会不断开始滴答updated_at。我猜它正在检测它本身对updated_at字段所做的更改。考虑到文档显示了这种更新的一个示例,这种行为让我很困惑。
https://firebase.google.com/docs/functions/firestore-events#writing_data
我是否缺少一个细微差别,或者这是一个Firestore错误?
答案 0 :(得分:1)
如果您检查文档中给出的示例,则会检查一个条件以查看name
是否已更改。如果是,则仅执行以下代码。如果它没有改变,只需return
s,就像这样:
// We'll only update if the name has changed.
// This is crucial to prevent infinite loops.
if (data.name == previousData.name) return;
因此,在您的情况下,您还需要检查对象的实际数据(除updated_at
之外的所有字段)是否已更改。如果没有别的(除了updated_at
),你应该退出该函数。
答案 1 :(得分:1)
要特别注意您引用的文档示例代码部分:
// We'll only update if the name has changed.
// This is crucial to prevent infinite loops.
if (data.name == previousData.name) return;
您需要找到一种方法来检测您的功能执行的更新何时触发同一位置的后续更新。
答案 2 :(得分:0)
在编写由自身触发的函数,但仅更改了updated_at字段时,可以检查先前的updated_at字段是否在新的updated_at字段的特定范围内。
以下代码位于您的云函数中
.onUpdate( async (change) => {
})
//exit if the last write happened within 5 seconds
if(change.after.data().updated_at - change.before.data().updated_at <= 5) {
return;
}
const date: Date = new Date();
try {
await db
.collection("collection_name")
.doc(change.after.id)
.set({ updated_at: date }, { merge: true });
} catch (e) {
functions.logger.log("failed updating doc in collection_name: ", e);
return false;
}
return true;
我使用5秒钟是因为 -我不在乎我的更新时间戳是否在5秒钟后关闭 -我不确定生产中会有多长时间的延迟(这种情况也适用于1秒,并且模拟器中的云功能大约每运行0.015秒就会运行一次)
答案 3 :(得分:0)
在 onUpdate 触发器中,添加或更新具有最新时间 (admin.firestore.fieldValue.serverTimestamp()
) 的文档的时间戳字段。对于本示例,我将调用时间戳变量 time
。
onUpdate
函数为您提供 before
和 after
文档。如果 before.time == after.time
,则您知道用户进行了更改。如果 before.time !== after.time
,则您知道云函数进行了更改。
if(snap.before.data().time !== snap.after.data().time){
// The cloud function altered the document.
// Return to prevent recursion!
return;
}
当您从客户端更新文档时,还要使用最新时间更新 time
变量。这样,云函数在执行所需代码之前不会终止。