Inf*_*tus 14 firebase google-cloud-functions google-cloud-firestore
在这种情况下,我使用的是循环函数,无法找到解决方案。
有一个我有一个标志的集合,该标志指示数据是否已更改。也要记录更改。
export async function landWrite(change, context) {
const newDocument = change.after.exists ? change.after.data() : null
const oldDocument = change.before.data()
const log = {
time: FieldValue.serverTimestamp(),
oldDocument: oldDocument,
newDocument: newDocument
}
const landid = change.after.id
const batch = db.batch()
const updated = newDocument && newDocument.updated === oldDocument.updated
if (!updated) {
const landRef = db.collection('land').doc(landid)
batch.update(landRef, {'updated': true })
}
const logRef = db.collection('land').doc(landid).collection('logs').doc()
batch.set(logRef, log)
return batch.commit()
.then(success => {
return true
})
.catch(error => {
return error
})
}
Run Code Online (Sandbox Code Playgroud)
问题在于,当UPDATED标志为false时,它将两次写入日志。但是也不能将日志写入ELSE语句中,因为该标志已经被UPDATED并且可以进行新文档更新,因此必须写入新日志。
触发:
import * as landFunctions from './lands/index'
export const landWrite = functions.firestore
.document('land/{land}')
.onWrite((change, context) => {
return landFunctions.landWrite(change, context)
})
Run Code Online (Sandbox Code Playgroud)
小智 5
如果我理解正确,这里的问题是该updated
标志未指定更新是响应哪个事件的(因为您实际上不能使用来做到这一点boolean
)。换句话说-您可能同时进行多个“第一阶段”写入lands
,因此需要一种消除它们歧义的方法。
我尝试了以下几种可能的选择-从(恕我直言)到最好:
lands
。选项1
在updated
字段中保存某种唯一标识符(例如,字符串化JSON事件的哈希-例如hash(JSON.stringify(oldDocument))
,或自定义事件ID [如果有的话])。
选项2
尝试检查updateMask
传入事件的属性,并丢弃仅影响该属性的所有写事件。
选项3
将更新状态存储在其他文档路径/集合(例如,与landUpdates
集合处于同一级别的lands
集合)中,并将您的云功能配置为不在该路径上触发。(如果需要,您始终可以创建另一个在路径上触发的Cloud Function,landUpdates
并向其添加相同或不同的逻辑。)
希望这可以帮助!
这里的主要问题是无法区分该服务器功能或客户端所做的更改。每当你处于这种情况时,你应该尝试明确区分它们。您甚至可以考虑使用一个额外的字段,fromServer: true
与服务器的更新一起使用,并帮助服务器忽略相关的触发器。话虽如此,我想我已经确定了问题所在,并在下面提供了明确的解决方案。
此行具有误导性:
const updated = newDocument && newDocument.updated === oldDocument.updated
Run Code Online (Sandbox Code Playgroud)
它应该被命名为:
const updateStatusDidNotChange = newDocument && newDocument.updated === oldDocument.updated
Run Code Online (Sandbox Code Playgroud)
我知道您希望更新后的标志由此函数而不是客户端管理。如果情况并非如此,请告诉我。
因此,更新字段仅在该函数中改变。由于您只想记录在此函数之外所做的更改,因此您只想在更新后未更改时记录。
这是我尝试从这个角度修复您的代码:
export async function landWrite(change, context) {
const newDocument = change.after.exists ? change.after.data() : null
const oldDocument = change.before.data()
const updateStatusDidNotChange = newDocument && newDocument.updated === oldDocument.updated
if (!updateStatusDidNotChange) return true; //this was a change made by me, ignore
const batch = db.batch()
if (!oldDocument.updated) {
const landid = change.after.id
const landRef = db.collection('land').doc(landid)
batch.update(landRef, {'updated': true })
}
const log = {
time: FieldValue.serverTimestamp(),
oldDocument: oldDocument,
newDocument: newDocument
}
const logRef = db.collection('land').doc(landid).collection('logs').doc()
batch.set(logRef, log)
return batch.commit()
.then(success => {
return true
})
.catch(error => {
return error
})
}
Run Code Online (Sandbox Code Playgroud)
我遇到了确切的问题,我必须区分服务器和客户端的更改,并忽略来自服务器的更改。我希望你能尝试一下我的建议。
归档时间: |
|
查看次数: |
169 次 |
最近记录: |