I have the following database structure in Firebase:
I would like to retrieve all objects from "chats" if in the "users" object contains the key "user2".
Is it possible to download the data as written with no change of structure Firebase?
My actually code to get data:
DatabaseReference chatReference = FirebaseDatabase.getInstance().getReference("conversationsNew");
chatReference.orderByChild("users").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d("TAG", dataSnapshot.getChildrenCount());
for (DataSnapshot chat : dataSnapshot.getChildren()) {
Log.d("TAG", chat.toString());
Chat chat = chat.getValue(Chat.class);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Thank you very much.
That's quite possible:
DatabaseReference chatReference = FirebaseDatabase.getInstance().getReference("chats");
chatReference.orderByChild("users/user1").equalTo(true).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot chat: dataSnapshot.getChildren()) {
Log.d("TAG", chat.getKey());
Chat chat = chat.getValue(Chat.class);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException(); // don't ignore errors
}
});
This will print:
chat1
But this approach will not scale, since you'll need to add an index for each user. To prevent this, you'll need a data structure that more closely reflects the use-case. So: if you want to show a list of the chats that the current user is in, you'll need to store precisely that: a list of the chats for each user. Alex' answer shows the most common way of storing such data.
No, there is no possibility for achieving this using your code. What can you do instead, is to change a little bit your database structure, by adding a new node like this:
Firebase-root
--- users
--- userId1
--- userName: John
--- chats
--- chat1: true
Having this, you can query your database for getting the chats in which your user belong. To verify for existens you only need to use exists() method on the dataSnapshot object.
Hope it helps.
Related
I am trying to retrieve a nested list of workouts from a Realtime Database and I don't know how to do it.
I made some research and still couldn't really figure out how am supposed to do it.
The Realtime Database JSON file looks like this :
I am looking to retrieve data by workout, for example, if someone presses the workout one button I should retrieve the full workout one object. but I don't know how am supposed to design my query request nor how am supposed to structure my model object that conceives the received data.
As I see in your screenshot, under the "Workout one" node, you have two nested levels of data. So to get all exercises for each day, you have to loop over the children twice:
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
DatabaseReference workoutOneRef = db.child("Fat Loss").child("Workout one");
workoutOneRef.get().addOnCompleteListener(new OnCompleteListener<DataSnapshot>() {
#Override
public void onComplete(#NonNull Task<DataSnapshot> task) {
if (task.isSuccessful()) {
for (DataSnapshot daySnapshot : task.getResult().getChildren()) {
for (DataSnapshot exerciseSnapshot : daySnapshot.getChildren()) {
String name = exerciseSnapshot.child("name").getValue(String.class);
Log.d("TAG", name);
}
}
} else {
Log.d("TAG", task.getException().getMessage()); //Never ignore potential errors!
}
}
});
Please also don't forget that the Firebase API is asynchronous. So any code that needs data from the database needs to be inside the onComplete() method, or be called from there. To understand better, I recommend you check the following resource:
How to read data from Firebase Realtime Database using get()?
I think below line code help you.
databaseReference = FirebaseDatabase.getInstance().getReference().child("Fat Loss").child("Workout one").child("day 1")
databaseReference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
allTaskList.clear();
if (snapshot.exists()) {
for (DataSnapshot dataSnapshot : snapshot.getChildren()) {
//modal class object
AddTODOListModal model = dataSnapshot.getValue(AddTODOListModal.class);
assert model != null;
model.setId(dataSnapshot.getKey());
allTaskList.add(model);
}
adapter = new TODOListAdapter(TODOListHomeActivity.this, allTaskList);
binding.rvTODO.setAdapter(adapter);
}else {
Utils.showToast("No Data Available");
}
Utils.dismissProgressDialog();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Utils.showToast(error.getDetails());
}
});
Reference link :- https://firebase.google.com/docs/database/android/lists-of-data
I do password recovery and I need to know if there is a user in the database with the entered E-mail'om. How do I do that? Here is the structure:
For example, the user entered E-mail - goshan164#gmail.com and I need to know if there is such a mail in my database. And if it exists, then find out the uID of the user with such mail. How do I do that?
P.S uId initially I do not know. In the picture uId = zKCTYc1JkROrGxgOZgvm9CvfSU42
You're looking for a Firebase database query, in this case one that compares the child property of each node against the value you're looking for:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users"); // or whatever your node is
Query query = ref.orderByChild("account").equalTo("goshan164#gmail.com");
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
System.out.println(userSnapshot.getKey());
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
For more on this, see the Firebase documentation on ordering an filtering data.
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 have structure for database in this manner
-... location
-... messages
-... id1_id2
-... id3_id4
-... id5_id6
.
.
.
How can I access a object in messages where I just know id1 which is the key.
TIA.
Change your database to this:
Messages
userid1
userid2
message: hello
then to retrieve message, do this:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Messages").child(userid1);
ref.addListenerForSingleValueEvent(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot){
for (DataSnapshot ds : dataSnapshot.getChildren()) {
String messages=ds.child("message").getValue().toString();
}
}
});
Try this one
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("location/messages");
ref.addListenerForSingleValueEvent(new ValueEventListener(){
#Override
public void onDataChange(DataSnapshot dataSnapshot){
for (DataSnapshot ds : dataSnapshot.getChildren()) {
if(ds.getKey().contains("bob")){
//Do something with the date
break;
}
}
}
});
Suppose your structure is like this:
You can do something like this, this will grab all nodes from messages that start with id1:
String id1 = "id1";
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("messages");
ref.orderByKey().startAt(id1).endAt(id1 + "\uf8ff").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot snap : dataSnapshot.getChildren()) {
Log.d("SNAP", snap.getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
I took the idea from the javascript implementation, but it also worked in Android, I've run a test on my device/database. Note that this method will work to grab data that starts with the given id.
EDIT:
The idea of querying firebase data that contains a certain string is discussed in this official post. Also, this question as well. The bottom line is that the api doesn't support these types of queries, the approach I mentioned above is the closest you can get of implementing a "SQL LIKE" in firebase. Currently, there's no way of searching for strings that END with another string. The endAt doesn't mean the string ends with id1, but rather that the range of values I want to retrieve finishes at (id1 + "\uf8ff"), that means any string starting with id1.
Your options are either change the schema or grab all messages and search locally (the suggestions of the other two answers).
I have been googling from 3 hours now but have not been able to either phrase the search term correctly or there are no good solutions for it. I am using firebase for my android app. It has a structure like following:
The upper one is comments node
I have just displayed the comments using listview.
commentRef1= FirebaseDatabase.getInstance().getReference().child("Comments").child(postKey1);
commentRef1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
for(DataSnapshot ds: dataSnapshot.getChildren()){
comment1=ds.getValue(Comment.class);
arrayList.add(comment1);
}
commentList.setAdapter(adapter);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
But as with every relational database, I am trying to save just id or uid in comments(table) or node(rather than whole username).
But, now I am having PROBLEM querying or DISPLAYING USERNAME while displaying comments from the users node (i.e display name) as uid only is saved in comments node.
I found some of the methods like doing nested oneventlistener and so on but little bit confused with the complications and effort need for it.
It would have been simple query or nested select in any sql languages.
Can anybody help? How can i retrieve username or specific value in that query. I saw many storing the while username in comments table. I don't think it is right approach.
To get the full_name, you need to do the following:
DatabaseReference ref=FirebaseDatabase.getInstance().getReference();
commentRef1= FirebaseDatabase.getInstance().getReference().child("Comments").child(postKey1);
commentRef1.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()){
for(DataSnapshot ds: dataSnapshot.getChildren()){
String userid=ds.child("uid").getValue().toString();
ref.child("Users").orderByKey().equalTo(userid).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String fullname=dataSnapshot.child("full_name").getValue().toString();
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
You can use nested listener, I guess you want the user to type the comment then click on a button and creates a node for the comment with a uid,post_id,comment.
Then you want to retrieve the comment to display it with the information, so the datasnapshot will be on Comments/postKey1 then you can retrieve the information there(including the uid), then use orderByKey().equalTo(userid) to be able to retrieve the fullname of the user from the node Users
To avoid all of this just add the fullname in the Comments node instead of the userid
https://firebase.googleblog.com/2013/04/denormalizing-your-data-is-normal.html