在间歇性和不可预知的情况下,Firebase实时数据库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()的对象中未包含的任何字段都将从实时数据库的目标记录中删除。
发布于 2018-12-21 07:46:46
对于1%的用户,数据库服务器的行为似乎不太可能有所不同。更有可能的是,1%的用户发出的呼叫中存在细微的差异。很难确定这与你分享的代码有什么不同,所以下面是一个有根据的猜测,希望能迅速解除你的封锁。
你说你愿意:
contactsRef.child(targetUID).child(contactID).update(contactObj);
预期: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
}
}但是现在假设您还想更新metadata/reputation。您可能认为这是可行的:
ref.update{
"name": "miles_b",
"id": 2687721,
"metadata": {
"reputation": 61
}
}但是在这里,您是在告诉数据库用您提供的对象替换metadata。所以结果是:
"uid1": {
"name": "miles_b",
"id": 2687721,
"full_name": "unknown",
"metadata": {
"reputation" 61
}
}这意味着last_seen现在已经从数据库中消失了。
若要更新嵌套属性,请在键中包含其完整路径。所以:
ref.update{
"name": "miles_b",
"id": 2687721,
"metadata/reputation": 61
}这样,您就可以在更新metadata/reputation的同时保留metadata/last_seen
"uid1": {
"name": "miles_b",
"id": 2687721,
"full_name": "unknown",
"metadata": {
"last_seen": "20 minutes ago",
"reputation" 61
}
}https://stackoverflow.com/questions/53877346
复制相似问题