Firebase database how to get nodes on based of the child value? - android

Actually i want to get online users only not the whole list of users.
This is my database structure:
Users
- Uid
- online : true
i want to get list of users which are online without needing to get each one of the user and then sorting it by checking the datasnapshot.

Assuming that Users node is a direct child of the Firebase root, i recomand you using the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef
.child("Users")
.child("Uid")
.orderByChild("online")
.equalTo(true);
query.addListenerForSingleValueEvent(/* ... */);
Edit1: If you don't have the uid of each user, please use the following code:
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference usersRef = rootRef.child("Users");
ValueEventListener eventListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String uid = ds.getKey();
Query query = usersRef.child(uid).orderByChild("online").equalTo(true);
query.addListenerForSingleValueEvent(/* ... */);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {}
};
usersRef.addListenerForSingleValueEvent(eventListener);
Edit2: As you can see in the offical documentation, addListenerForSingleValueEvent adds a listener for a single change in the data at this location. This listener will be triggered once with the value of the data at the location.
When you write data and if you'd like to know when your data has been committed, you can add a OnCompleteListener which is called when the Task completes. Both setValue() and updateChildren() methods take an optional completion listener that is called when the write has been committed to the database. This is an example:
yourRef.setValue("I'm writing data", new Firebase.CompletionListener() {
#Override
public void onComplete(FirebaseError firebaseError, Firebase firebase) {
if (firebaseError != null) {
System.out.println("Data could not be saved. " + firebaseError.getMessage());
} else {
System.out.println("Data saved successfully.");
}
}
});
Regarding synchronizing, there is a common way to detect when Firebase is done synchronizing the initial data on a given location. This approach makes use of one of the Firebase event guarantees:
Value events are always triggered last and are guaranteed to contain updates from any other events which occurred before that snapshot was taken.
So if you have both a ValueEventListener and a ChildEventListener on a given location, the ValueEventListener.onDataChange() is guaranteed to be called after all the onChildAdded() calls have happened.
But one thing to keep in mind: Firebase doesn't just load data. It continuously synchronizes data from the server to all connected clients. As such, there is not really any moment where the data is completely retrieved. That's why you need to remove the listener as explained below.
Furthermore, note that you can remove the listener whenever you want. The best practice is to remove it accordingly to the life-cycle of your activity.
If you have added the listener in onStart you have to remove it in onStop.
If you have added the listener in onResume you have to remove it in onPause.
If you have added the listener in onCreate you have to remove it in onDestroy.
But remember onDestroy is not always called.
databaseReference.removeEventListener(valueEventListener);

You can filter your items by specifying the child and value like this:
ref.orderByChild("online").equalTo(true);
More info here: https://firebase.google.com/docs/database/android/lists-of-data

Use this code
ref.child('Uid')
.orderByChild('online')
.equalTo(true);
or use
FirebaseDatabase.getReference("Users").child("Uid").orderByChild("online").equalTo(true);

Related

Having trouble deleting node in firebase database

I'm having some trouble deleting nodes in Firebase
This is how I upload my data
BigBoy add = new BigBoy(addCate);
myRef.push().setValue(add);
This is how i'm trying to delete my data
databaseReference = FirebaseDatabase.getInstance().getReference().child("message");
myRef = database.getReference("message");
String sfasf = Utils.object.getSfasf();
DatabaseReference remove = FirebaseDatabase.getInstance().getReference("message").child(sfasf);
remove.removeValue();
But the problem is that the node is not being deleted.
Make your firebase call like this -
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("message");
reference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot dataSnapshots : dataSnapshot.getChildren()){
if (dataSnapshots.child("sfasf").exists()) {
dataSnapshots.child("sfasf").removeValue();
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
1) You have a reference object but you dont use it. You have created 2 variable references and you dont use them.
2) Your code is wrong in order to remove the node you must specify the key
myRef = database.getReference("message");
myRef.child(key).remove();
---edit---
try this
myRef.child(key).removeValue();
---edit---
From the official documentation:
The simplest way to delete data is to call removeValue() on a reference to the location of that data. You can also delete by specifying null as the value for another write operation such as setValue() or updateChildren(). You can use this technique with updateChildren() to delete multiple children in a single API call.
The problem was that I wasn't referencing the pushID when I was referencing the specific data node. That was solved by saving the key as well when I upload the data.

Firebase "addListenerForSingleValueEvent" keeps getting old values that no longer is in Firebase database?

I keep getting the old values (which no longer is in the database) from my Firebase database. Here is how the database looks right now:
I am getting the info under friendlist. It used to be only one child there with key-value set soosk: true, but now it looks like in the photo. When using addListenerForSingleValueEvent() to my databaseRef, the friendlist retrieved only has soosk: true in it. Here is my code:
mFirebaseDatabaseReference = FirebaseDatabase
.getInstance()
.getReference(
"users/"+FirebaseAuth.getInstance().getCurrentUser().getUid()
);
mFirebaseDatabaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
Log.d(TAG, user.getFriendlist().toString());
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
The method you need to use to have all the values updated is addValueEventListener(). Because you need to listen for more than one value this is the only way to achieve it and to use addListenerForSingleValueEvent().
The most important thing is to remove the listener in your onDestroy method like this:
yourReference.removeEventListener(valueEventListener);

How to search for a values of Child in firebase Android

DatabaseReference databaseReference=mDatabase;
String queryText="Hotel";
databaseReference.orderByChild("Coupon")
.startAt(queryText)
.endAt(queryText+"\uf8ff");
Here I attached the code which I used to get child names of "Coupon" when I entered the "Hotel" query under the Coupon.But I got blank.I supposed to get Hotel1,Hotel2 object.I'm new to firebase.So hope your support .Thanks in advance.
In the Web version, they use something called ElasticSearch, you could try to read more here: https://firebase.googleblog.com/2014/01/queries-part-2-advanced-searches-with.html
But for Android, I think there isn't any functionality to perform a search like that. What I would do is to query all the records then filter them myself:
DatabaseReference databaseReference = mDatabase;
mDatabase.addValueEventListener(new ValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot val : dataSnapshot.getChildren()){
//I am not sure what record are you specifically looking for
//This is if you are getting the Key which is the record ID for your Coupon Object
if(val.getKey().contains("Hotel")){
//Do what you want with the record
}
//This is if your are querying for the hotel child
if(val.child("hotel").getValue(String.class).contains("Hotel")){
//Do what you want with the record
}
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
}
Don't load your whole database to filter out needed data. It produces unnecessary traffic which has to be loaded, calculated and deleted. Instead, use:
DatabaseReference myRef = FirebaseDatabase.getDatabaseReference();
Query searchQuery = myRef.child("Coupon").orderByChild("hotel").equalTo("yourSearchString");
To make this code work, you also have to add indexOn on your corresponding attribute in the rules (of Firebase Database console).

Push list of data to firebase not working

I am trying to use the firebase push() function, as I want to add a list off data to an allready existing list. The setValue() function overwrites existing data.
This is what I used to do:
DatabaseReference childref = mDatabase.child("users").child(uih.getUserData().getUsername()).child("answered_questions");
childref.setValue(getAnsweredQuestions(questionViewList));
This worked, but every time I use this function the data is overwritten and this is not what I want. I tried using the Push function as described by the firebase documation: https://firebase.google.com/docs/database/android/save-data
I am not sure I am doing it right, but it is not working. And this is when I tried to implement the push() function:
DatabaseReference childref = mDatabase.child("users").child(uih.getUserData().getUsername()).child("answered_questions");
String key = childref.push().getKey();
Map<String, Object> childUpdates = new HashMap<>();
childUpdates.put( key, questionViewList);
mDatabase.updateChildren(childUpdates);
The exception I get is:
com.google.firebase.database.DatabaseException: Failed to parse node with class class scrambled.nl.generationr.QuestionView
And this is weird, since I did not receive this error while doing the setValue method. Can anyone explain what I am doing wrong and how I should push a list to firebase?
edit:
What I can do is:
DatabaseReference childref = mDatabase.child("users").child(uih.getUserData().getUsername()).child("answered_questions");
childref.push().setValue(getAnsweredQuestions(questionViewList));
In added the push() here. This works, but instead of just increasing my list, i add another layer in my list so I actually get an array of arrays instead of a longer list.
See here the result:
Saving a List of AnsweredQuestion objects:
This assumes you've followed the rules when designing your AnsweredQuestion.class so that the Java object can be used to store data in Firebase. If you need guidance for that check under the "Basic write operations" heading for saving data in the documentation.
//List of AnsweredQuestions
List<AnsweredQuestion> mAllAnswers;
....
//create the database reference that points to the correct parent node
//where answeres are stored for each user
DatabaseReference ref = mDatabase.child("users").child(uih.getUserData().getUsername()).child("answered_questions");
//Iterate over your List of AnsweredQuestion objects and use push() along with setValue()
//to store a single AnsweredQuestion object to a unique location in your database.
for(AnsweredQuestion answer : mAllAnswers){
ref.push().setValue(answer);
}
Retrieve all answered questions for a user:
//create List to store AnsweredQuestion object
List<AnsweredQuestion> mAllAnswers = new ArrayList<AnsweredQuestion>();
...
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//iterate over datasnapshot to get/store each AnsweredQuestion object
if(datSnapshot.exists()){
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
AnsweredQuestion answer = snapshot.getValue(AnsweredQuestion.class);
mAllAnswers.add(answer);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
//handle error
}
});
There are multiple ways to retrieve the answers for each user, using .addListenerForSingleValueEvent() is just one way. You can also use a FirebaseListAdapter or FirebaseRecyclerAdapter if you wanted to display the answers in a ListView or RecyclerView.

My program can't get result from addChildEventListener in Firebase

DB structure
questions
questionId
options
optionId
label
score
...
First I created a database reference in my code .
mQuestionDatabaseReference = FirebaseDatabase.getInstance().getReference("questions").child(questionId).child("options").child(optionId);
Then inside an option I changed the value of score using transaction.
mQuestionDatabaseReference.child("score").runTransaction(new Transaction.Handler() { ...
I can successfully update score value. Now I want to know if the score is already updated in the database so I can update my UI using addChildEventListener.
mQuestionDatabaseReference.addChildEventListener(new ChildEventListener() {..
This one is okay. Now, I just wanna know if the score child of the option is updated not the whole option. So I did thid
mQuestionDatabaseReference.child("score").addChildEventListener(new ChildEventListener() {..
Now this new child event listener can't get the result when I successfully update an option.
You are adding a ChildEventListener in /optionId/score but score doesn't actually have any child, so the callback will never be triggered.
In this case you should be using ValueEventListener.
mQuestionDatabaseReference.child("score").addValueEventListener(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//dataSnapshot.getValue ...
}
});
Get more info in firebase events documentation.

Categories

Resources