Reputation: 51
at the moment users are stored in my real-time firebase database.
The User-Class contains:
private String uid;
private UserPermissions userPermissions;
private List<Item> items;
The list items is empty by default, which results into the following database structure:
A Button is used to add an item to the list of the current user.
Currently I'm trying to update the database by the whole user object, like this:
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();
}
});
Which results into the following:
The hierarchy is broken.
Is there any other possiblity to update the lists items of an existing user without setting the whole user object to the database? If not, how would it be possible to prevent this problem?
How would it be possible to update the user similiar to the MySQL syntax with a where condition?
UPDATE `ingredients` SET `ingredient` = `new_value' WHERE `uid` = `PClW...`;
Thanks for the help in advance!
Upvotes: 3
Views: 1843
Reputation: 6354
Its probably helpful to keep in mind that in the Firebase RTDB data model, a given node contains all of its children, always, in their entirety. There isn't really a concept of tables, or even "collections" that you might find in Firestore.
This is important because you are calling setValue()
which sets the reference that you call it for to the exact value passed -- it performs a full replacement. In the words of the documentation:
Using setValue() in this way overwrites data at the specified location, including any child nodes.
In this case, the reference you are using is pointing at the users
node, not at the node for the current user. So, what you see is that the entire users
node is replaced with the value for a single user.
You have two options.
The first and most straightforward is to get a reference to the node of the specific user you want to update call setValue
on that:
ref = FirebaseDatabase.getInstance().getReference()
.child("users").child(uid);
Note that the uid
here is actually the key for the node you are trying to update (in this case -LuxronyXRi8s85SBvVf
). It is not the value of the uid child of that node. If you need to find the key because you do not know it, you will need to either iterate through all the children of the users
node yourself until you find it or try to find it via a filter query.
Of course, there is no guarantee (at least not any that Firebase RTDB provides) that only one child node has that particular uid
value.
Further, if you just want to update one field below the user node, then just get a reference to that instead (again, the uid here refers to the key of the node you want to update):
ref = FirebaseDatabase.getInstance().getReference()
.child("users").child(uid).child("userPermissions");
Alternatively, if you want to write to multiple children of a node, while leaving the other child nodes in place, you can use updateChildren()
. See documentation here and the reference here. This can take a map of child paths to values to update to, but is likely more complicated than you need in this case since you appear to be trying to update exactly one user, in its entirety.
Upvotes: 2