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
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?
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(...)?
I've connected my android app to firebase and enabled email and password authentication. My current database status is like :
Now I want to add an extra field (key:"number")for all users i have so that my final database looks like:
so please tell me how can I do this ?
One more important thing is I wrote code such that I first authenticate them, if their registration is succesfull then I take user to new Activity where they will enter this "key" after collecting the key I should add this to user node as shown in the second picture.
So please tell me how to do this?
To write a value in the Firebase Realtime Database, you must know the complete path to that value. So in your case that means that you first have to load all data from the database, to be able to determine the dynamic keys (C76w3..., FjsZ..., etc).
Something like this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot: dataSnapshot.getChildren()) {
snapshot.getRef().child("key").setValue("hisoka");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
I'm running an Android app that handles some data on Events and Users who have been invited to them. I have a page that needs to show all the events that a user has been invited to, but I'm relatively new to Firebase and I'm not sure how the query syntax would work for my current data structure.
An example of my data-structure (with dummy keys) can be seen below:
events
event1_key
eventName: "test event"
eventAdmin: "userAdmin"
eventInvites
user1_key
attending: true
responseTimestamp: 1525416294951
user2_key
//...
event2_key
//...
eventInvites
user2_key
//...
user3_key
//...
So using this example, if I was looking for all the events that user1_key had been invited to, the query should only return the event1_key record, because that one has a nested eventInvite for user1_key.
If I'm running that query in Java for Android Studio, does anybody know what it should look like?
I think you need to replicate your data in another node in this case. Right now, you have a single node which keeps all the events (i.e. events node). I would suggest your create a separate table (i.e. separate node) for users as well.
That node structure might look like the following.
users
user1_key
events1_key
events2_key
...
user2_key
events5_key
events2_key
....
....
I this way you will not require any nested lookup. Just replicate the data here in this node as well when you are inserting the data under events node.
Hope that helps!
Update
If you are considering replicating your table, then the check for user is attending an event will be fairly simple like the following.
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
boolean attending = false;
for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
if(eventSnapshot.getKey().equals(THE_DESIRED_EVENT)) {
attending = true;
break;
}
}
if(attending) doSomethingAsUserIsFoundToBeAttendingTheEvent();
else userIsNotAttending();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The code is not tested, I just have the pseudo implementation. Please modify as per your need.
To achieve what you want, I recommend add another node in your database structure that looks like this:
Firebase-root
|
--- userEvents
|
--- user1_key
|
--- event1_key: true
|
--- event2_key: true
In this way you'll be able to read all your events that correspond to a particular user at once without the need to download the enitire events object. To get those ids, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference userKeyRef = rootRef.child("userEvents").child(userKey);
ValueEventListener valueEventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String eventKey = ds.getKey();
Log.d("TAG", eventKey);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
userKeyRef.addListenerForSingleValueEvent(valueEventListener);
I'm trying to make a chat application using firebase database but I'm having some problems.
This is my database. I want to add a listener to Messages but just for the values for User->UID->chats->Chat IDs. How can I do this?
You need to do it twice: first get the chat id list based on user id, then get the messages data for each of those chat ids.
// consider you have you user (FirebaseUser) object ready
FirebaseDatabase.getInstance().getReference("Users/" + user.uid + "/chats")
.addListenerForSingleValueEvent(new ValueEventListener() {
... onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
FirebaseDatabase.getInstance().getReference("Messages/"+snapshot.getKey())
.addListenerForSingleValueEvent(...
... onDataChange(DataSnapshot messageSnapshot) {
// I changed the snapshot name to make it easier to read
// here messageSnapshot.getKey() is message ID
// and messageSnapshot.getValue() will contain data you need (I think)
}
...
);
}
}
...
});
Hope this helps
Here is an example to access
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference reference = database.getReference("Messages").child(read);