I am having a hard time with figuring out how to query my Firebase database. Here is what it looks like.
And here is my code:
//RETRIEVE
public ArrayList<Spacecraft> retrieve()
{
String myUserId = acct.getId();
//db.addChildEventListener(new ChildEventListener() {
db.child("/users/uid").equals(myUserId)
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
//fetchData(dataSnapshot);
fetchData(dataSnapshot);
adapter.notifyDataSetChanged();
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
fetchData(dataSnapshot);
adapter.notifyDataSetChanged();
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return spacecrafts;
}
So db.addChildEventListener will retrieve the entire database. But what I want is to only retrieve data for users whose uid is equal to String myUserId. And I want to sort in ascending order by Level. I have read the docs and watched videos but I cannot figure it out. Any help would be appreciated.
Query query = db.child("users").orderByChild("uid").equalTo("myUserId");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot userSnapshot: snapshot.getChildren()) {
System.out.println("User "+userSnapshot.child("uid").getValue());
}
}
...
But if you're frequently accessing the data by UID, you're off restructuring your database to store all users under their own UID:
users
myUserId
Level: 2
NumCorrect: 8
You can then read the data with:
db.child("users/myUserId").addValueEventListener(new ValueEventListener() {
public void onDataChange(DataSnapshot snapshot) {
fetchData(dataSnapshot);
}
For more on Firebase queries, see the Firebase documentation on sorting and filtering data. Since you're new to NoSQL, I also recommend reading NoSQL data modeling and viewing Firebase for SQL developers.
You can reverse the array list
ArrayList<UserModel> user_list = new ArrayList<>();
for (DataSnapshot snapshot :dataSnapshot.getChildren()) {
UserModel userModel = snapshot.getValue(UserModel.class);
user_list.add(userModel);
Collections.reverse(user_list);
}
Related
I have a DataSnapshot with all keys of Firebase runtime database. Here is my log:-
E/MYDATA: DataSnapshot { key = Income, value = {-LgaZl_ojnqmvgpPe48D={date=2019-06-05, createdAt=2019-06-05 13:08:22, amount=333.00, caption=jjhj, from=yyyyy, time=13:08, type=ICICI Bank, updatedAt=2019-06-05 13:08:22}} }
E/MYDATA: DataSnapshot { key = createdAt, value = 2019-06-05 11:06:18 }
E/MYDATA: DataSnapshot { key = email, value = abc#gmail.com }
Here my LOG is = MYDATA , I try to key = Income data render in Recyclerview
Here is my code :
String id = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users").child(id);
ref.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Log.e("MYDATA", "" + dataSnapshot);
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
and here is my database structure :-
Database image
Look this image
If you want to fetch the records of "Expanse", change the ref to,
DatabaseReference ref = FirebaseDatabase.getInstance().getReference().child("Users").child(id).child("Expanse");
After changing it, add a ValueEventListener or ChildEventListener to the ref.
You've used ChildEventListener, so in the onChildAdded of ChildEventListener, you can get the data from Firebase like,
Expanse expanse = dataSnapshot.getValue(Expanse.class);
list.add(expanse);
Above code will come in onChildAdded of ChildEventListener, where Expanse is your POJO class in which you have getters and setters for amount, caption, date, etc.
Then you have to add this newly obtained object expanse in the List, and then notify your RecyclerViewAdapter that the data was changed.
I'm doing my project.
My project is App for finding room in my campus.
In my database there are room name, floor, building room and location.
I want to find all records that have a keyword that the user want to find.
And show data about that room.
My firebase
Refer this link for complete code
http://www.amalhichri.net/android-firebase-realtime-database-basic-cruds/
private void findperson(String name){
Query deleteQuery = myDatabaseReference.orderByChild("fullName").equalTo(name);
deleteQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Iterable snapshotIterator = dataSnapshot.getChildren();
Iterator iterator = snapshotIterator.iterator();
while((iterator.hasNext())){
Log.d("Item found: ",iterator.next().getValue().toString()+"---");
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}`enter code here`
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d("Item not found: ","this item is not in the list");
}
});
}
Change your firebase url to
"YourFireBaseUrl/room/cb1201" to get the data of room no cb1201
you will get the data in JSON format
I want to get particular value using from DataSnapshot.
I am attaching the screenshot here so kindly check and help me to get particular value from Realtime Database.
Actually I am implementing chat application in which I want to get value of user from group_list.
Here is my code.
private void loadTotalGroupList() {
referenceMainUrl = FirebaseDatabase.getInstance().getReferenceFromUrl("https://pure-coda-174710.firebaseio.com");
referenceGroupList = referenceMainUrl.child("group_list");
//Check if child is available or not.
referenceGroupList.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Log.e("dataSnapshot"," ==>"+dataSnapshot);
Map<String, Object> newPost = (Map<String, Object>) dataSnapshot.getValue();
Log.e("newPost"," ==>"+newPost);
Log.e("user: ","==>" + newPost.get("user")); // Here I am getting null value
} else {
Log.e("Child not found", " >>>");
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
and log showing like this. DataSnapshot { key = group_list, value = {First Group={-KtBH9gnTszNxcXjNu9A={message=assaasas, user=sakib}}} }
I have resolved my issue by using addChildEventListener
referenceGroupList.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String prevChildKey) {
Log.e("dataSnapshot KEY", " ==>" + dataSnapshot.getKey());
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String prevChildKey) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String prevChildKey) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here dataSnapshot.getKey() returns all sub child of it.
You're listening to the location /group_list in your code. That means a a snapshot from that location will contain the following:
/First Group
/-KtBH9gnTszNxcXjNu9A
message = "..."
user = "..."
If you want to get the user value from that location, you'll have to dig into it using each intermediate path:
dataSnapshot.child("First Group").child("-KtBH9gnTszNxcXjNu9A").child("user").getValue()
Or more simply:
dataSnapshot.child("First Group"/-KtBH9gnTszNxcXjNu9A/user").getValue()
You can't skip the middle paths in the snapshot. Alternatively, you may want to listen to a location closer to the value you want:
referenceMainUrl.child("group_list/First Group/-KtBH9gnTszNxcXjNu9A");
This code runs in a loop and gives you values for all the 'user's
DatabaseReference dRef = FirebaseDatabase.getInstance().getReference().child("group_list").child("First_Group");
dRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot snapshot : dataSnapshot.getChildren()){
String userName = snapshot.child("user").getValue(String.class);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
How do I search for users based on their usernames? I have looked at numerous SO posts on this matter but am still unable to achieve what I want to do.. I have tried to apply what I saw in those posts and is shown below:
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("users");
usersRef.orderByChild("username")
.startAt(queryText)
.endAt(queryText+"\uf8ff");
usersRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
searchList = new ArrayList<>();
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
User user = postSnapshot.getValue(User.class);
Log.d("USER: ", "" + user.getUsername());
searchList.add(user);
}
adapter = new UserCardAdapter(getContext(), searchList);
recyclerView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e("onQueryTextChange: " ,databaseError.getMessage());
}
});
However, all users are still retrieved. I have seen the usage of startAt() and endAt() supposedly work for others on other posts but I cannot manage to get it to work for me..
This is how the user data is stored:
User Data Structure
You almost done right but you should add addListenerForSingleValueEvent after the database reference that already apply orderBy() , startAt(), endAt() like this.
usersRef.orderByChild("username")
.startAt(queryText)
.endAt(queryText+"\uf8ff")
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
searchList = new ArrayList<>();
for (DataSnapshot postSnapshot: snapshot.getChildren()) {
User user = postSnapshot.getValue(User.class);
Log.d("USER: ", "" + user.getUsername());
searchList.add(user);
}
adapter = new UserCardAdapter(getContext(), searchList);
recyclerView.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.e("onQueryTextChange: " ,databaseError.getMessage());
}
});
Your use of orderBy(), startAt(), and endAt() is correct according to the documentation.
But the addListener method must be applied directly to the object returned by the chain of orderByChild(), startAt(), and endAt() methods, and not in a new statement on the DatabaseReference retrieved with ... .getReference("users").
If you use a ChildEventListener:
DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("users");
usersRef.orderByChild("username")
.startAt(queryText)
.endAt(queryText+"\uf8ff");
.addChildEventListener(new ChildEventListener() {
List<User> searchList = new ArrayList<>();
#Override public void onChildAdded(DataSnapshot dataSnapshot, String s) {
User user = dataSnapshot.getValue(User.class);
Log.d("USER: ", "" + user.getUsername());
searchList.add(user);
}
#Override public void onChildChanged(DataSnapshot dataSnapshot, String s) {}
#Override public void onChildRemoved(DataSnapshot dataSnapshot) {}
#Override public void onChildMoved(DataSnapshot dataSnapshot, String s) {}
#Override public void onCancelled(DatabaseError databaseError) {}
});
I'm starting to use firebase and everything looks great but I have 50k records to show inside a recyclerview and I can't figure out how to paginate or something similar because load everything at once takes too much time.
I used childEventListener and FirebaseUI as well with no luck.
UPDATE 1:
Finally I got working for the update 1, this is not the best solution for this but I think I'm going to make some changes later.
private String lastKey = null;
private List<Comment> commentList = new ArrayList<>();
private final static int QUERY_LIMIT = 20;
private int page = 0;
private void loadComments() {
page++;
ChildEventListener childEventListener = new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
Comment comment = dataSnapshot.getValue(Comment.class);
commentList.add(comment);
adapter.notifyDataSetChanged();
lastKey = String.valueOf(comment.getTimestamp());
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
if (lastKey != null) {
commentList.clear();
adapter.notifyDataSetChanged();
comments.child(id_post).orderByChild("timestamp").endAt(lastKey).limitToLast(QUERY_LIMIT * page).addChildEventListener(childEventListener);
} else {
comments.child(id_post).orderByChild("timestamp").limitToLast(QUERY_LIMIT).addChildEventListener(childEventListener);
}
}
You can add a value event listener to limit the number of of results you would like to receive, here is a quick example from firebase-ui
ref.limitToLast(5).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot msgSnapshot: snapshot.getChildren()) {
Chat msg = msgSnapshot.getValue(Chat.class);
Log.i("Chat", chat.getName()+": "+chat.getText());
}
}
Use the method limitToLast(5) to get the last 5 objects that were added. Other methods with regards to this include limitToFirst(), limitToLast(), startAt(), endAt(), and equalTo()
More information can be found Here.
I am using this method to show 8 Million Records stored in the Real-time Database, 50 at a time with pagination.
private void getUsers(String nodeId) {
Query query;
if (nodeId == null)
query = FirebaseDatabase.getInstance().getReference()
.child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
.orderByKey()
.limitToFirst(mPostsPerPage);
else
query = FirebaseDatabase.getInstance().getReference()
.child(Consts.FIREBASE_DATABASE_LOCATION_USERS)
.orderByKey()
.startAt(nodeId)
.limitToFirst(mPostsPerPage);
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
UserModel user;
List<UserModel> userModels = new ArrayList<>();
for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) {
userModels.add(userSnapshot.getValue(UserModel.class));
}
mAdapter.addAll(userModels);
mIsLoading = false;
}
#Override
public void onCancelled(DatabaseError databaseError) {
mIsLoading = false;
}
});
}
You also don't have to store the last key separately.
If you are not able to understand it fully then you can read the blog post here which explains everything.