This question already has answers here:
Firebase Query Double Nested
(3 answers)
Closed 2 years ago.
I have "orderStatus" node type integer in my database, and I need to query it by its value(0, 1, 2, etc.). It works okay if I user orderByChild("orderStatus"), but I don't want to be downloading all data and order it, I just want to download data with specific "orderStatus". That's where I run to my problem, when I put equalTo(statusInteger) I don't get any data from the database.
What am I doing wrong, am I using equalTo wrong or something?
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Orders");
Query orderRef = databaseReference
.child(restaurantId)
.orderByChild("orderStatus")
.equalTo(0);
orderRef.addListenerForSingleValueEvent...
To be able to query the database by a specific property, you need to add all child names that exist in that particular hierarchy. In your query, you are missing a child. Between the "restaurantId" node and the actual Order object, which holds the "orderStatus" property, there is one more node, which is "LPG ... CQ2", and I'm assuming the UID of the logged-in user. To make it work, please use the following lines of code:
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference uidRef = rootRef.child("Orders").child("Restaurant01").child(uid);
Query orderStatusQuery = uidRef.orderByChild("orderStatus").equalTo(0);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String userName = ds.child("userName").getValue(String.class);
Log.d("TAG", userName);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d("TAG", databaseError.getMessage()); //Don't ignore potential errors!
}
};
orderStatusQuery.addListenerForSingleValueEvent(valueEventListener);
The result in the logcat will be:
User
Edit:
According to your comment, what you are looking for it's actually not possible with your actual database structure. Besides that, filtering on the client it's definitely not an option in this scenario.
However, the best I can think of is to create another node that stores all orders, of all users. In this way, you can query using ".orderByChild("orderStatus").equalTo(0)" and you'll get the desired results. This practice is called denormalization and is a common practice when it comes to Firebase. For a better understanding, I recommend you see this video, Denormalization is normal with the Firebase Realtime Database.
what if you Start with .equalTo(... ) then .orderBy(...)?
Related
I am using the Firebase Realtime Database with Android in Java. I have the following database screenshot:
I would like to change the availability value (from 0 to 1) for the ingredient with the attribute "ingredient_name = Lime". The attribute ingredient_name is actually something like a primary key meaning that there will be no other database entry with this specific name.
I tried the following code
DatabaseReference rootRef;
rootRef = FirebaseDatabase.getInstance("https://....app").getReference();
String ingredientToBeUpdate = "Lime";
rootRef.child("ingredients").orderByChild("ingredient_name").equalTo(ingredientToBeUpdate).child("availability").setValue(1);
But I get the error "Cannot resolve method 'child' in 'Query'". Can you tell me how to do this update properly? So I would like to update the value from the database entries who attribute "ingredient_name" is equal to a certain string ingredientToBeUpdate.
Firebase doesn't support so-called update queries, where you send a condition and the new data to the database and it them writes the new data for all nodes matching the condition.
Instead you will need to execute the query in your application code, loop through the results, and update each of them in turn:
rootRef
.child("ingredients")
.orderByChild("ingredient_name")
.equalTo(ingredientToBeUpdate)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot ingredientSnapshot: dataSnapshot.getChildren()) {
ingredientSnapshot.getRef().child("availability").setValue(1);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
Also see:
Firebase Android, set value where x = x?
Is it possible to update a specific child's value without ID or key in firebase realtime database from android on button click?
I have a firebase database I am using with Android.
To Retrieve and show data from Firebase, I am using FirebaseRecyclerAdapter and results are displayed to CardView.
Now I am getting all listings from my required table to CardView. Every Node has an automatically generated value as shown in the image below.
How do I retrieve this value in Android when I click on respective CardView. I'll need this value for further database operations.
Now, I tried some of the methods posted here as well as online forums but nothing seems to work. I am not asking for complete code, just how to do it? Some reference code would be great.
Regards
To get the node id try the following:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("Projects");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String key = ds.getKey();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
Log.d(TAG, databaseError.getMessage());
}
};
query.addListenerForSingleValueEvent(valueEventListener);
First, add a reference to node Projects then loop inside of it and retrieve the id using getKey().
I'm new in firebase Firestore and when i tried to write this code with Firestore I faced a problem.
DatabaseReference mDisplayData = FirebaseDatabase.getInstance().getReference().child("Users").child(postKey);
com.google.firebase.database.Query firstQuery = mDisplayData.limitToFirst(20);
firstQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()){
String nameData = dataSnapshot.child("name").getValue().toString();
String statusData = dataSnapshot.child("status").getValue().toString();
String imageData = dataSnapshot.child("thumb_image").getValue().toString();
userViewHolder.setDetails(getApplicationContext(),nameData,statusData,imageData);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
});
the problem was in this line of code :
Query firstQuery = firebaseFirestore.collection("Users").document(postKey).collection(null);
what i want to do is to create a firestore query but i want to stop only in postkey refrence the thing that is not possible what should i do.
please help and thank you.
firstQuery in the following line of code:
Query firstQuery = firebaseFirestore.collection("Users").document(postKey).collection(null);
Is of type Firestore Query and is not of type Firebase real-time database Query. So there is no way in which you can call addListenerForSingleValueEvent() on such an object. What you are actually trying to do, is to use code that can get the data from Firebase real-time database on Firestore query, which obviously is not possible.
To solve this, you need to use a get() call on your firstQuery object and then attach a listener. But first I recommend you read the official documentation regarding getting data with Cloud Firestore.
I have a Firebase database with a node "items" that has many children and I would like to import a list of the children keys. Since each child contains quite some data that I am not interested in for this purpose, I would like to download only the children keys (to minimize the amount of data transferred). For illustration, suppose I have the following data structure:
Then I would like to get the id's of all the users, so 5Aoz6ZaB9QS7o9M4lsdbh07VGA02 etc. But without downloading the other user data such as the messages, name, proposed and score.
To get the ids of those users, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("users");
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String uid = ds.getKey();
Log.d("TAG", uid);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(valueEventListener);
The output will be:
5Aoz6ZaB9QS7o9M4lsdbh07VGA02
// the other ids
When you attach a listener on a specific node, you get all the data beneath that node. This is how Firebase Realtime database works and unfortanately this behaviour cannot be changed. But there is an workaround in which you can create another separate node in which you can add all those ids separately. The new node should look something like this:
Firebase-root
|
--- userIds
|
--- 5Aoz6ZaB9QS7o9M4lsdbh07VGA02: true
|
--- //other ids
In this case, if you attach a listener on userIds node, you'll get only the desired data and nothing more. The code to get those ids is simmilar with the code above, but instead of using .child("users") you need to use .child("userIds"). The output will be the same.
If you want another behaviour, you can consider using Cloud Firestore where this behaviour isn't an issue anymore.
You can use shallow=true parameter. It will return only the first layer of results (keys), follower by true.
A request to /users.json?shallow=true
would return the following:
{
5Aoz6ZaB9QS7o9M4lsdbh07VGA02: true,
900xwQqVBMOOBUBFbQTeyjwhFsc2: true,
RqwVZgV5cWd1fwkWm2ibuSX0Zfe2: true,
bnDyoXg2sXPJoSAuvdHjkFBLdao2: true,
fitCihcRwYQOpza7nsdawCHJ6Bn1: true,
}
check more in: https://firebase.google.com/docs/database/rest/retrieve-data
This question already has answers here:
Is it possible to update only specific data on my child on firebase?
(2 answers)
Closed 4 years ago.
I have a button on my Android app that when pressed should update the score in the Firebase database;
// UPDATE DATABASE START
final String getArgument = getArguments().getString("matchid");
DatabaseReference database = FirebaseDatabase.getInstance().getReference();
final DatabaseReference ref = database.child("Matches");
final Query gameQuery = ref.orderByChild("gameID").equalTo(getArgument);
gameQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
if(snapshot.exists()){
for (DataSnapshot child: snapshot.getChildren()) {
ref.child(getArgument).child("homeScore").setValue(5);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
//UPDATE DATABASE END
When I execute the code I get a new record in the database instead of updating the existing fields data. I've hand cranked the database through the Firebase console instead of programmatically updating the records, so I use gameID that I created as my PK in the DB.
I've hard coded the value to be updated to 5 to get it working first.
The data structure in Firebase is;
-Matches
- Match_01
-matchID
-homeScore
-etc....
All help appreciated.
To update, you need to do this:
DatabaseReference ref=FirebaseDatabase.getInstance().getReference().child("Matches").child("Match_01");
Map<String, Object> updates = new HashMap<String,Object>();
updates.put("matchID", newID);
updates.put("homeScore", newscore);
//etc
ref.updateChildren(updates);
more info here:
https://firebase.google.com/docs/database/android/read-and-write#update_specific_fields
To simultaneously write to specific children of a node without overwriting other child nodes, use the updateChildren() method.