Node.js Firebase实时数据库-间歇更新()与set()类似
Firebase实时数据库Node.js Firebase实时数据库-间歇更新()与set()类似,node.js,firebase,firebase-realtime-database,google-cloud-functions,firebase-admin,Node.js,Firebase,Firebase Realtime Database,Google Cloud Functions,Firebase Admin,Firebase实时数据库update()函数的工作方式似乎与set()函数的工作方式类似,这是间歇性的、不可预测的。有趣的是,它似乎发生在大约1%的更新操作上。但是我们已经执行了大量的日志记录,并且会看到一些事情发生,比如一个特定的更新被推送到一个循环中的一组用户,我们验证是否在日志中向所有用户发送了正确的信息,并且对每个记录调用了update()。然而,我们将看到的结果是,有时其中一个用户会得到一个只包含我们更新的字段的记录,而记录中的所有其他字段都会被删除,而所有其他用户都会正确地接收更新
update()
函数的工作方式似乎与set()
函数的工作方式类似,这是间歇性的、不可预测的。有趣的是,它似乎发生在大约1%的更新操作上。但是我们已经执行了大量的日志记录,并且会看到一些事情发生,比如一个特定的更新被推送到一个循环中的一组用户,我们验证是否在日志中向所有用户发送了正确的信息,并且对每个记录调用了update()
。然而,我们将看到的结果是,有时其中一个用户会得到一个只包含我们更新的字段的记录,而记录中的所有其他字段都会被删除,而所有其他用户都会正确地接收更新。随后运行完全相同的update()
操作将导致所有内容按预期更新。这是一个已知的问题吗?有什么解决办法吗?我们正在节点8.14.0上运行firebase admin 6.0.0
尝试对update()函数进行多次重复测试。没有可靠的方法可以使这个问题重现,但它是在生产中随机发生的
const contactsRef = admin.database().ref().child('contacts');
...
//targetUID, contactID, contactObj get passed in via PubSub
...
contactsRef.child(targetUID).child(contactID).update(contactObj);
预期:update()
只应更新传递给它的记录字段
实际:
update()
似乎像set()
一样随机工作,大约有1%的时间。将从实时数据库中的目标记录中删除传递给update()
的对象中未包含的任何字段。对于1%的用户,数据库服务器的行为似乎不太可能不同。更有可能的是,这1%的用户拨打的电话略有不同。很难确定这与您共享的代码有什么区别,因此下面是一个有根据的猜测,希望能快速解除您的阻止
你说你会:
预期:update()
只应更新传递给它的记录字段
这有点微妙,不幸的是,您没有展示如何构造contactObj
。所以我会举个例子。假设您从JSON开始:
"uid1": {
"name": "unknown",
"id": -1,
"full_name": "unknown",
"metadata": {
"last_seen": "20 minutes ago",
"reputation" 56
}
}
您可以在该位置运行此命令:
ref.update{
"name": "miles_b",
"id": 2687721
}
在这种情况下,仅更新ref
下的name
和id
属性。其他属性未经修改,因此您最终会得到:
"uid1": {
"name": "miles_b",
"id": 2687721,
"full_name": "unknown",
"metadata": {
"last_seen": "20 minutes ago",
"reputation" 56
}
}
但是现在,假设您还想更新元数据/声誉
。你可能认为这是可行的:
ref.update{
"name": "miles_b",
"id": 2687721,
"metadata": {
"reputation": 61
}
}
但是这里您告诉数据库用您提供的对象替换元数据。因此,结果是:
"uid1": {
"name": "miles_b",
"id": 2687721,
"full_name": "unknown",
"metadata": {
"reputation" 61
}
}
这意味着上次看到的现在已经从数据库中消失了
要更新嵌套属性,请在键中包含其完整路径。因此:
ref.update{
"name": "miles_b",
"id": 2687721,
"metadata/reputation": 61
}
这样,您就可以在更新元数据/声誉时保留元数据/最后一次查看
:
"uid1": {
"name": "miles_b",
"id": 2687721,
"full_name": "unknown",
"metadata": {
"last_seen": "20 minutes ago",
"reputation" 61
}
}
正如我提到的,我们已经执行了大量的日志记录,以确保在调用update()函数时,正确的信息被传递到该函数中。对于任何特定的用户来说,这并不是始终如一的,而是在所有用户之间随机发生的。一两分钟后执行完全相同的更新可能会导致正确的预期行为。发生此错误时,将从数据库中的记录中删除更新调用中未明确包含的任何字段。与往常一样:如果显示问题的最小完整细节,将更容易提供帮助。我明白了,向我们展示如何重现这一点可能很难/不可能,但展示独立代码和日志表明它没有达到预期的效果应该是可能的。如果不是,我建议在故障排除方面提供个性化帮助,因为他们可能会查看您的项目中的奇怪之处。不过,他们通常也会先要求代码+日志记录,除非他们看到多个报告
"uid1": {
"name": "miles_b",
"id": 2687721,
"full_name": "unknown",
"metadata": {
"last_seen": "20 minutes ago",
"reputation" 61
}
}