首页 > 解决方案 > 如何正确更新 firebase-realtime-database 中的对象?

问题描述

目前,用户存储在我的实时 firebase 数据库中。

用户类包含:

private String uid;
private UserPermissions userPermissions;
private List<Item> items;

列表默认为空,这导致以下数据库结构:

在此处输入图像描述

Button 用于将项目添加到当前用户的列表中。

目前我正在尝试通过整个用户对象更新数据库,如下所示:

ref = FirebaseDatabase.getInstance().getReference().child("users");
[...]
Button dialogButton = (Button) dialog.findViewById(R.id.addItem);
dialogButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        ref.setValue(user);
        dialog.dismiss();
    }
});

结果如下:

在此处输入图像描述

层次结构被打破。

是否有任何其他可能性来更新现有用户的列表项而不将整个用户对象设置为数据库?如果没有,如何防止这个问题?

如何使用 where 条件更新类似于 MySQL 语法的用户?

UPDATE `ingredients` SET `ingredient` = `new_value' WHERE `uid` = `PClW...`;

我在这里先向您的帮助表示感谢!

标签: javaandroidfirebasefirebase-realtime-database

解决方案


请记住,在 Firebase RTDB 数据模型中,给定节点始终包含其所有子节点,这可能会有所帮助。Firestore 中并没有表的概念,甚至没有“集合”的概念。

这很重要,因为您正在调用setValue()它将您调用它的引用设置为传递的确切值 - 它执行完全替换用文档的话来说:

以这种方式使用 setValue() 会覆盖指定位置的数据,包括任何子节点。

在这种情况下,您使用的引用指向users节点,而不是当前用户的节点。因此,您看到的是整个users节点被替换为单个用户的值。

你有两个选择。

第一个也是最直接的方法是获取对要更新调用的特定用户的节点的引用setValue

ref = FirebaseDatabase.getInstance().getReference()
        .child("users").child(uid);

请注意,uid这里实际上是您尝试更新的节点的-LuxronyXRi8s85SBvVf(在这种情况下)。它不是该节点的 uid 子节点的值。如果您因为不知道密钥而需要找到它,您将需要自己遍历节点的所有子users节点,直到找到它,或者尝试通过过滤器查询找到它。

当然,不能保证(至少 Firebase RTDB 不提供任何保证)只有一个子节点具有该特定uid值。

此外,如果您只想更新用户节点下方的一个字段,则只需获取对该字段的引用(同样,这里的 uid 是指您要更新的节点的键):

ref = FirebaseDatabase.getInstance().getReference()
        .child("users").child(uid).child("userPermissions");

或者,如果您想写入一个节点的多个子节点,同时保留其他子节点,您可以使用updateChildren(). 请参阅此处的文档和此处参考。这可以将子路径映射到要更新的值,但在这种情况下可能比您需要的更复杂,因为您似乎正在尝试完全更新一个用户。


推荐阅读