How to modify an specific value in Firebase? - android

I have this data in Firebase Database:
Negocios:
-KjfCu56lFZCybYldBZy
lugarReference: "Restaurante"
numeroMesas:39
password:"pass123"
user:"user123"
user_id:"usr_1"
I have two applications connected to one project in Firebase, one of them upload data of restaurants reservation, and the other one displays reservations in a RecyclerView.
In the first application, once I do a reservation, it must minus one to numeroMesas value, the other application should display any changes to this key.
In the reservation application, I have this piece of code that I did base in this question:
Update specific keys using Firebase for Android
It supposes to modify the value of numeroMesas, but it does not:
mReference.child("Negocios").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot postSnapshot : dataSnapshot.getChildren()){
Lugar lugar = postSnapshot.getValue(Lugar.class);
if(nombre_lugar.equals(lugar.getUser_id())){
DatabaseReference numMesasReference = mReference.child(dataSnapshot.getKey()).child("numeroMesas");
numMesasReference.setValue(lugar.getNumeroMesas() - 1);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
What it does is the next thing:
Negocios:
-KjfCu56lFZCybYldBZy
lugarReference: "Restaurante"
numeroMesas:39
password:"pass123"
user:"user123"
user_id:"usr_1"
-Negocios
-KjfCu56lFZCybYldBZy
numeroMesas:39
How can be fixed?
I need to minus one once I do a reservation...
Greetings!

Using postSnapshot.getRef() you obtain a reference to the source location for this snapshot. So what's next is to add a child to that reference, that reference will be "numeroMesas" that is the key you want to modify.
As easy as that, the code will be like this.
mReference.child("Negocios").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot postSnapshot : dataSnapshot.getChildren()){
Lugar lugar = postSnapshot.getValue(Lugar.class);
if(nombre_lugar.equals(lugar.getUser_id())){
DatabaseReference numMesasReference = postSnapshot.getRef().child("numeroMesas");
numMesasReference.setValue(lugar.getNumeroMesas() - 1);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
P.S: If you want to minus one just once by reservation, addValueEventListener() won't work, it will minus multiple time as a loop. Use addListenerForSingleValueEvent() instead addValueEventListener().
As the name says, this listener fits for single changes in the data at any location.

I guess the problem is with dataSnapshot.getKey() in this line
DatabaseReference numMesasReference = mReference.child(dataSnapshot.getKey()).child("numeroMesas");
Here you getting the key for the whole list of Negocios, not for the specific child replace it with `
postSnapshot.getKey()

The problem is that your DatabaseReference that you are using is wrong. You are missing a child. So in order to solve this problem, please use the following code:
mReference.child("Negocios").child(negociosId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
int numeroMesas = (int) dataSnapshot.child("numeroMesas").getValue();
if(nombre_lugar.equals(lugar.getUser_id())){
mReference.child("Negocios").child(negociosId).child("numeroMesas").setValue(numeroMesas - 1);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
In which negociosId is the unique id generated by the push() method.
Hope it helps.

I'm new to firebase and android. But If the above solutions doesn't work please do the following. I think the problem is that you didn't convert the value of numeroMesas to string. Sorry if there's anything wrong.
Hope it helps.
mReference.child("Negocios").child(negociosId).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(nombre_lugar.equals(lugar.getUser_id())){
mReference.child("Negocios").child(negociosId).child("numeroMesas").setValue((Integer.parseInt(dataSnapshot.child("numeroMesas").getValue().toString())) - 1);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});

Related

Retrieve Firebase data who have specific child

Please check my database image. I want to select and display all users who have parent = chris
my database image
To retrieve the users that contain parent : chris, you can do the following:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("users");
reference.orderByChild("parent").equalTo("chris").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String name = datas.child("name").getValue(String.class);
String key = datas.getKey();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
orderByChild.equalTo is a query that will retrieve all the nodes that contain parent equal to chris.
Since you tagged this as a android studio question I assume you are using the Firebase SDK.
You should check out the documentation, where they explain how you can query in a lot of languages with very nice examples.

Firebase Child Event Listener to every child last node

I could not figure out how to point my value listener to every child's last node as shown in this picture.
I think I need to use childevent listener but I don't know how to redirect it correctly.
Query searchItemQuery = userDatabaseReference.child(user.getUid());
searchItemQuery.addChildEventListener(new ChildEventListener(){
#Override
public onChildAdded, onChildChanged, onChildRemoved, onChildMoved, onCancelled
});
I would suggest that down for each item0001, item0002, instead of using firebase push id, you can store the unix timestamp in millis. That way you can easily sort your entries and get last child node for each item.
So, with this change your database would look like
root
user
uid
item0001
15089344450000 // this is a timestamp
itemdepositdate
itemwithdrawdate
15989922000000 // another timestamp
itemdepositdate
itemwithdrawdate
item0002
AND SO ON...
Now, for each item, you can point to last child simply by using below code.
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.getReference()
.child("root")
.child("user")
.child("user_id_of_user")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()){
snapshot.getRef().orderByKey().limitToLast(1).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
dataSnapshot.getValue(); // this is the last itemdepositdate and itemwithdrawaldate for this item
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Query searchItemQuery = userDatabaseReference
.child(user.getUid)
.orderByKey() //order nodes w.r.t. the keys
.limitToLast(1); //gets last item

ArrayList gets empty after first snapshot

I'm working with firebase in a android application and something strange ocurred, in my example I need two snapshots, 1 to get the users inside a list ( I use this snapshot to fill a arraylist of strings with the key of the user) and the other to compare to the users, the strange behavior is that my arraylist is empty after the first snapshot, I used logcat to check it and that Log inside the firstsnapshot returns me 1 as the size of the arraylist, the second returns me 0, dunno how it gets 0 again.
Here is my code:
private void prepareFriendList() {
myRef.child(id).child("FriendLists").child(group).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String keyUser;
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Log.d("number:",snapshot.getKey());
keyUser = snapshot.getKey();
currentFriends.add(keyUser);
Log.d("hello",String.valueOf(currentFriends.size()));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
for(String s: currentFriends){
Log.d("idddd",s);
}
Log.d("hello",String.valueOf(currentFriends.size()));
myRef.child(id).child("Users").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
User user = snapshot.getValue(User.class);
for(String item: currentFriends){
if (snapshot.getKey().equals(item)) {
usersList.add(user);
}
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
mAdapter.notifyDataSetChanged();
}
I don't understand why that happens, since I'm adding the key inside the arraylist, any tip?
This is happening because onDataChange is called asynchronously. This means that the statement that adds users to the list is executed before onDataChange has been called. That's why your list is empty outside that method. So in order to use that lists, you need to use it inside the onDataChange() method.
For other approach, please visit this post and this post.
Hope it helps.

How to retrieve particular nodes in Firebase Realtime Database?

I'm making a post app with Firebase Realtime Database.
The app needs a bookmark function, but I don't know how to load the bookmarked (selected) post.
Database structure:
Code:
databaseReference = databaseReference.child("post").child(getLen()).child("all-posts").child("-KYbMBatKdoWYw45-2pp").child("bookmarkUsers").orderByChild(myUserId).equalTo(myUserId);
but this code is not working. Why doesn't it work? I think that it only returns bookmarkUsers child node.
Do I have to make another node only for bookmark?
I already made a node only for bookmark, but I could't manage bookmardCount and starCount synchronization.
Thanks!
DatabaseStorage Posts=FirebaseDatabase.getInstance().getReference().child("posts");
Posts.child("0").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot DS: dataSnapshot)
{
//Get all other Values Except bookmarkusers and store them
String POST_NAME = dataSnapshot.getKey();
Posts.child("0").child(POST_NAME)addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshotf) {
for(DataSnapshot BOOK: dataSnapshotf)
{
//Collect all BookMarks and store them
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Do I have to make another node only for bookmark?
Yes, you do. To get more information, read about structuring you data in firebase here.
I already made a node only for bookmark, but I could't manage bookmardCount and starCount synchronization.
You will need to keep the bookmarkCount and starCount inside the post node itself.

How to retrieve all objects from a Node in Firebase database?

I followed the documentation, but no matter what, I cannot figure out how to return all the objects from a single node. For example, I want to return a list of all company objects from the companies node. Once I have that list, I want to parse them all into JSON objects. This is my first time with a NoSQL database so I'm sure that I'm missing something small.
Currently I have:
DatabaseReference companiesRef = FirebaseDatabase.getInstance().getReference("12265");
companiesRef.child("companies").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("Count ", dataSnapshot.getChildren().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
But it just returns null for the value: DataSnapshot { key = companies, value = null }.
Here's my database:
You create your reference like this:
FirebaseDatabase.getInstance().getReference("12265");
This means that Firebase looks at the root of the database and returns the child 12265 from under there. It does not automatically search the tree for a node with a matching name.
So you'll need to specify the entire path:
FirebaseDatabase.getInstance().getReference("android/users/12265");
Don't add any parameters to your getReference() (let it go to the root of database) and then set the addListenerForSingleValueEvent. And you have not used getvalue() on you datasnapshot as well. Try this code:
DatabaseReference companiesRef = FirebaseDatabase.getInstance().getReference();
// this is the patch that I see from the image that you have attached.
companiesRef.child("telenotes").child("android").child("user").child("12265").child("companies").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("Count ", dataSnapshot.getChildren().getValue().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});

Categories

Resources