You can migrate to Cloud Firestore but if you are already using the Firebase real-time database you can achieve this, but not without some changes in your database.
I want to get all the books from a specific author and I am wondering what is the best way to do it?
Unfortunately, you cannot achieve what you you using your actual database structure. To get all the books from a specific author, you should consider augmenting your data structure to allow a reverse lookup. That implies you to create a new top level collection named books
in which you should store as book
objects all the books of a particular author. You database schema should look like this:
Firebase-root
|
--- books
|
--- authorIdOne
|
--- bookIdOne
| |
| --- id: "bookIdOne"
| |
| --- nameInEnglish: "nameInEnglish"
| |
| --- nameInSinhalese: "nameInSinhalese"
|
--- bookIdTwo
|
--- id: "bookIdTwo"
|
--- nameInEnglish: "nameInEnglish"
|
--- nameInSinhalese: "nameInSinhalese"
To get all the books from a specific author you need to attach a listener on its id (authorIdOne
) and loop through its children.
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference yourRef = authorIdOneRef.child("books").child(authorIdOne);
authorIdOneRef.addListenerForSingleValueEvent(/* ... */);
How to find out whether the author has books under their name?
To solve this, you need to use exists()
method on the DataSnapshot
object. Assuming you are using a model class named Book
, please see the following lines of code:
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
Book book = ds.getValue(Book.class);
Log.d("TAG", book.getNameInEnglish());
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {}
};
authorIdOneRef.addListenerForSingleValueEvent(valueEventListener);
But the same thing can be achieved using the String class.
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if(dataSnapshot.exists()) {
for(DataSnapshot ds : dataSnapshot.getChildren()) {
String nameInEnglish = ds.child("nameInEnglish").getValue(String.class);
Log.d("TAG", nameInEnglish);
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {}
};
authorIdOneRef.addListenerForSingleValueEvent(valueEventListener);
And note, the Firebase real-time database doesn't store arrays. What you are actually having is an object. See here more details.