In my Android app I am using this code to retrieve posts from firebase database:
ArrayList<Post> posts = new ArrayList<>();
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot dsp : dataSnapshot){
String author = dsp.child("author").getValue().toString();
String text = dsp.child("author").getValue().toString();
posts.add(new Post(author,text));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
But this returns all the posts and if there would be many of them I think it wouldn't be good idea to keep them all in memory. Is there a way to get only certain number of node's children? For example at the beginning I would like to get 10 first ones, then 10 more and so on
You're looking for limitToFirst() (or limitToLast()).
ArrayList<Post> posts = new ArrayList<>();
Query query = dbRef.orderByKey().limitToFirst(10);
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot dsp : dataSnapshot){
String author = dsp.child("author").getValue().toString();
String text = dsp.child("author").getValue().toString();
posts.add(new Post(author,text));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
See the Firebase documentation on queries for an explanation of all its capabilities.
You need to use your DataSnapShot to retrieve more specific information.
There is a Firebase guide for Android that explain how to utilize: Firebase Android Guide
If you would prefer to see on Stack OverFlow a small example this answer here seems to be doing somewhat of what you would like to achieve: Firebase Get Children
Related
Please check my database image. I want to select and display all users who have parent = chris
my database image
To retrieve the users that contain parent : chris, you can do the following:
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("users");
reference.orderByChild("parent").equalTo("chris").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot datas: dataSnapshot.getChildren()){
String name = datas.child("name").getValue(String.class);
String key = datas.getKey();
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
orderByChild.equalTo is a query that will retrieve all the nodes that contain parent equal to chris.
Since you tagged this as a android studio question I assume you are using the Firebase SDK.
You should check out the documentation, where they explain how you can query in a lot of languages with very nice examples.
A part of my current Firebase Database looks like this:
I have only expanded one to show you the general structure of the JSON tree.
Within the "medium" child, I have 3 more sub-children of "a bit of both", "nature" and "urban". I already know how to extract the mappings under each trail (trailA, trailB, etc) in Android but I am not sure how to loop through the 3 sub-children mentioned above. Is it a for loop for DatabaseReferences or something else? My current code works but it is very inefficient, particularly when the data grows even bigger.
I am really new to Firebase and am only beginning to understand the structuring so please forgive me if this question is relatively basic. Any help (and further explanations) would be deeply appreciated.
My current code for extracting data from the sub-children is in the form of hard-code:
List<DatabaseReference> dbList = new ArrayList<>();
DatabaseReference refB = firebaseDatabase.child("medium").child("a bit of both");
DatabaseReference refC = firebaseDatabase.child("medium").child("nature");
DatabaseReference refC = firebaseDatabase.child("medium").child("urban");
dbList.add(refB);
dbList.add(refC);
for (DatabaseReference x : dbList) {
x.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds : dataSnapshot.getChildren()) {
TrailInformation ti = ds.getValue(TrailInformation.class);
trailInformationCallback.onCallBack(ti);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
I'm making a post app with Firebase Realtime Database.
The app needs a bookmark function, but I don't know how to load the bookmarked (selected) post.
Database structure:
Code:
databaseReference = databaseReference.child("post").child(getLen()).child("all-posts").child("-KYbMBatKdoWYw45-2pp").child("bookmarkUsers").orderByChild(myUserId).equalTo(myUserId);
but this code is not working. Why doesn't it work? I think that it only returns bookmarkUsers child node.
Do I have to make another node only for bookmark?
I already made a node only for bookmark, but I could't manage bookmardCount and starCount synchronization.
Thanks!
DatabaseStorage Posts=FirebaseDatabase.getInstance().getReference().child("posts");
Posts.child("0").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot DS: dataSnapshot)
{
//Get all other Values Except bookmarkusers and store them
String POST_NAME = dataSnapshot.getKey();
Posts.child("0").child(POST_NAME)addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshotf) {
for(DataSnapshot BOOK: dataSnapshotf)
{
//Collect all BookMarks and store them
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Do I have to make another node only for bookmark?
Yes, you do. To get more information, read about structuring you data in firebase here.
I already made a node only for bookmark, but I could't manage bookmardCount and starCount synchronization.
You will need to keep the bookmarkCount and starCount inside the post node itself.
I'm new to Firebase and NoSQL. I have an Android Demo, with a City Autocomplete Text Field in which I want to populate the cities I have from my Firebase DB, while typing.
{ "cities":{
"Guayaquil":true,
"Gualaceo":true,
"Quito":true,
"Quevedo":true,
"Cuenca":true,
"Loja":true,
"Ibarra":true,
"Manta":true
}
}
This is what I have so far.
How can I retrieve from the DB cities that start with a letter (input from keyboard)? If I start typing "G", I want to receive "Guayaquil" and "Gualaceo".
If I use orderByValue always returns an empty snapshot.
If I use orderByKey return the whole list.
Query citiesQuery = databaseRef.child("cities").startAt(input).orderByValue();
citiesQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<String> cities = new ArrayList<String>();
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
cities.add(postSnapshot.getValue().toString());
}
Note: If you can recommend a better data structure, you're welcome.
#NicholasChen has identified the problem. But here's the way you'd implement using the 3.x SDK:
DatabaseReference cities = databaseRef.child("cities")
Query citiesQuery = cities.orderByKey().startAt(input).endAt(input+"\uf8ff");
citiesQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<String> cities = new ArrayList<String>();
for (DataSnapshot postSnapshot: dataSnapshot.getChildren()) {
cities.add(postSnapshot.getValue().toString());
}
By starting at the user input and ending at the last string that starts with the user input, you get all matching items
For relatively short lists of items Ryan's approach will also work fine. But the above Firebase query will filter server-side.
Update
I just ran this code:
DatabaseReference databaseRef = FirebaseDatabase.getInstance().getReference("39714936");
String input = "G";
DatabaseReference cities = databaseRef.child("cities");
Query citiesQuery = cities.orderByKey().startAt(input).endAt(input + "\uf8ff");
citiesQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
List<String> cities = new ArrayList<String>();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
cities.add(postSnapshot.getValue().toString());
}
System.out.println(cities);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
And it printed:
true
true
So clearly matches two cities.
Feel free to test against my database: https://stackoverflow.firebaseio.com/39714936
Try something like this to iterate over the children in the cities snapshot and add all the cities to an ArrayList of Strings.
ArrayList<String> cityList = new ArrayList<>();
databaseRef.child("cities").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
cityList.clear();
for (DataSnapshot data : dataSnapshot.getChildren()){
cityList.add(data.getKey);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.w(TAG, "getUser:onCancelled", databaseError.toException());
// ...
}
});
Editing this paragraph for clarity:
This will get all your cities read into the program memory so you can use that data to display the cities to the user. If the city list changes, so will the data the user sees. If the user is not online, this will not work. This puts a real time, online only listener on the database.
The logic in my mind is something like:
Set a value listener on the text box.
When user types, make a view display all the items in the array list
that start with the same substring that was typed.
Handle arrayIndex errors of course.
Hopefully this will get you on the right track. I am sure there are other ways you could implement it but this is what I would personally do. If you need help with the code to display the correct cities, start a chat with me and I can brainstorm with you.
Of course OrderByValue returns nothing because that's the booleans you have.
you can use the startAt and endAt methods to do so. (The below is Firebase 2.0's Code)
var ref = new Firebase("https://dinosaur-facts.firebaseio.com/dinosaurs");
ref.orderByKey().startAt("b").endAt("b\uf8ff").on("child_added", function(snapshot) {
console.log(snapshot.key());
});
You can explore more on the Firebase 3 documentation site here.
What Ryan did was right. However, you have to implement startAt on the dataSnapshot to make sure that your "live" search works.
This is my JSON Tree in the Firebase Realtime database. I just want to iterate and read through all of the items under questions. I think I am doing something silly wrong.
Under the "My App" - I have a "questions" branch and saving a bunch of data under it. Below is the tree and my code. In the code I point out the part that is crashing. Circled in red below are what I am trying to read.
public void readfromFireDB() {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference().child("questions");
// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
**THIS IS THE ERROR, ques comes back as NULL**
Question ques = dataSnapshot.getValue(Question.class);
String key = dataSnapshot.getKey();
}
#Override
public void onCancelled(DatabaseError error) {
}
});
}
This Issue: ques in onDataChanged() comes back as a null reference. May be I am not accessing the children under questions properly?
By using a ValueEventListener you're accessing the list of questions, not an individual question.
To access each individual question, you'll need to loop over the snapshot:
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot questionSnapshot: dataSnapshot.getChildren()) {
Question ques = questionSnapshot.getValue(Question.class);
String key = questionSnapshot.getKey();
}
}