5

I am making a chat app, and I have a Firebase with following Structure. Chat1,Chat2,Chat3... is used for saving data of different Chat groups. Message1,Message2,Message3 are Messages inside 1st group., It can be from any author.

Chats

  • Chat1
    • Message1
      • Author1
      • MessageText
    • Message2
      • Author2
      • MessageText
    • Message3
      • Author1
      • MessageText
  • Chat2
    • Message1
      • Author3
      • MessageText
    • Message2
      • Author4
      • MessageText
    • Message3
      • Author1
      • MessageText
  • Chat3

I want to retrieve the list of all Messages from "Author 1". Meaning Message1,Message3 should be retrieved from Chat1 and Message3 also should get retrieved from Chat2. I want to display all messages from 1 author.

ref = new Firebase(FIREBASE_URL); //Root URL

ref.addValueEventListener(new ValueEventListener() {

    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
         for (DataSnapshot child : dataSnapshot.getChildren()) {
                 for (DataSnapshot childd : child.getChildren()) {
                     //This might work but it retrieves all the data
                    }
                }
    }

    @Override
    public void onCancelled() {

    }
});

This Gives me entire data! How do I restrict it to "Author1"?

engico
  • 453
  • 1
  • 5
  • 9

3 Answers3

11

Firebase will always retrieve the complete node(s) that you ask for. Since you're asking for all Chats or an entire Chat at once (it isn't clear which one you do from your code), that's what you get.

If you want to get less data from Firebase, you'll have to be more specific in what you ask from it. For example if you want to display Chat1, then start by listening for the children of the Chat1 node.

This snippet comes from the Firebase guide for Android:

// Retrieve new posts as they are added to Firebase
ref.addChildEventListener(new ChildEventListener() {
    // Retrieve new posts as they are added to Firebase
    @Override
    public void onChildAdded(DataSnapshot snapshot, String previousChildKey) {
        Map<String, Object> newPost = (Map<String, Object>) snapshot.getValue();
        System.out.println("Author: " + newPost.get("author"));
        System.out.println("Title: " + newPost.get("title"));
    }
    //... ChildEventListener also defines onChildChanged, onChildRemoved,
    //    onChildMoved and onCanceled, covered in later sections.
});

This snippet accomplishes the same as your current example, but instead of your code looping over the data with a for, Firebase feeds you the data one message at a time.

With that in place, you can filter the messages. This is a two-step process: first you order by a child node, then you limit which nodes are returned.

Query query = ref.orderByChild("Author").equalTo("Author1", "Author");
query.addChildEventListener(new ChildEventListener() {
    // the rest of the code remains the same as above

This last bit is best explained in the Firebase documentation on queries.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks for the reply, I will try this... Looks like I am use old Firebase Library. – engico Nov 28 '14 at 14:30
  • I upgraded the library and tried various things, I am able to retrieve messages from 1 node from 1 author. But I want to retrieve all messages of author 1 from all nodes. – engico Nov 28 '14 at 14:52
  • 1
    Aha... that is not possible at the moment. `orderByChild` goes one level deep. You can always build your own index, that maps messages to authors. See http://stackoverflow.com/questions/16638660/firebase-data-structure-and-url/16651115#16651115. That was also the way to do this before Firebase added the `orderByChild` method, so other older answers may contain good examples for you to look at. – Frank van Puffelen Nov 28 '14 at 15:14
1

I don't know if this is what you meant or not, but here is my code for my database. First here is my database structure:

*Root of Database

:Users

:

:....username1

: :

: :......"Name":"value"

: :......"Email":"value"

: :......"Password":"value"

:

:....username2

: :

: :......"Name":"value"

: :......"Email":"value"

: :......"Password":"value"

Here is my code for retrieve the data from database:

FirebaseDatabase database= FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference().child("Users");

login=myRef.child(name); //here user will sign in using his name so it is based on user, directory will change dynamically
ValueEventListener listener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {

            User user = dataSnapshot.getValue(User.class);

            String demo=user.Email;
            //email fetched from database
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    };
    login.addValueEventListener(listener);

Here the User.java class contains 3 String values of email,password & name.

public class User {

public String Name;
public String Email;
public String Password;

public User() {
    // Default constructor required for calls to DataSnapshot.getValue(User.class)
}

public User(String name,String pass, String email) {
    this.Name = name;
    this.Email = email;
    this.Password = pass;
}
}
1

You can use the Query to filter the results

DatabaseReference mDatabaseReference = FirebaseDatabase.getInstance().getReference("Chat1");
   Query query =  mDatabaseReference.orderByChild("authorName").equalTo("Author1");

Additionally use can other filter methods given here: https://firebase.google.com/docs/reference/android/com/google/firebase/database/Query

Pramod Garg
  • 2,183
  • 1
  • 24
  • 29