2

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: firebase db 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.

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
TheGooooogle
  • 263
  • 3
  • 11
  • Note that duplicating data is completely normal in NoSQL database. If you're new to that, read [NoSQL data modeling](https://highlyscalable.wordpress.com/2012/03/01/nosql-data-modeling-techniques/), and watch [Firebase for SQL developers](https://www.youtube.com/playlist?list=PLl-K7zZEsYLlP-k-RKFa7RyNPa9_wCH2s). – André Kool Apr 11 '18 at 12:32
  • are you able to get user id who commented on that post.? – Atif AbbAsi Apr 11 '18 at 12:49

1 Answers1

2

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

Peter Haddad
  • 78,874
  • 25
  • 140
  • 134
  • Thanks. Ya I was trying to avoid nested datasnap listeners. Anyways, that was giving me a null reference error so changed a little bit. It is giving me full name but set function (setUsername) is not working if we put it inside second eventlistener does not work...I am sure it is entering into second listener, as logcat is showing the fullname but setname function works if i put outside the second eventlistener but does not work if it is inside second one, as follows... – TheGooooogle Apr 12 '18 at 00:25
  • for(DataSnapshot ds: dataSnapshot.getChildren()){ .....comment1.setComment(ds.child("comment").getValue().toString()); //comment1.setUsername("user name1"); works userRef.child(userid).addValueEventListener(new ValueEventListener() { public void onDataChange(DataSnapshot dataSnapshot) { String fullname=dataSnapshot.child("full_name").getValue().toString(); Log.w("fullname", fullname); comment1.setUsername(fullname);//doesnot work } – TheGooooogle Apr 12 '18 at 00:27
  • I tried making fullname as a global variable and tried accessing outside that second listener...didn't work Log.w("fullname", fullname); – TheGooooogle Apr 12 '18 at 00:41
  • add fullname as global variable but retrieve it and use it inside the second listener and not outside, also change the `addValueEventListener`'s to `addSingleValueEventListener` – Peter Haddad Apr 12 '18 at 06:52
  • I tried that earlier didn't work comment1=new Comment(); comment1.setComment(ds.child("comment").getValue().toString()); //comment1.setUsername("user name1"); //works userRef.child(userid).addListenerForSingleValueEvent(new ValueEventListener() {public void onDataChange(DataSnapshot dataSnapshot) { fullname=dataSnapshot.child("full_name").getValue().toString(); comment1.setUsername(fullname); //not working } public void onCancelled(DatabaseError databaseError) { – TheGooooogle Apr 12 '18 at 09:14
  • yes it is working. Setting inside that second listener does not work...setting above it in first listener works but off course there i do not have fullname – TheGooooogle Apr 12 '18 at 09:16
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/168808/discussion-between-peter-haddad-and-thegooooogle). – Peter Haddad Apr 12 '18 at 09:18
  • there is no error at all...but it does not get set...nothing appears for that textbox....other things are working as I say if i set it in first listener it is working.... – TheGooooogle Apr 12 '18 at 09:19
  • If it helps https://i.imgur.com/kuC4fde.png but since the same thing is working if put in first listener so may not be problem in other place... – TheGooooogle Apr 12 '18 at 09:24
  • do it as in the answer, retrieve the uid and then do orderBykey().equalTo(userid) instead of child(userid) – Peter Haddad Apr 12 '18 at 09:24
  • ya when i did that i got this error java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String java.lang.Object.toString()' on a null object reference thats why i changed it – TheGooooogle Apr 12 '18 at 09:42
  • are you using AddSingleValueEventListener in the two listeners first and second, not only second – Peter Haddad Apr 12 '18 at 09:47
  • Thanks for taking time. Yes I have been done it. Still null ref error. Please see the latest changes in this image. And also in the comment inside the comment https://i.imgur.com/loYVMvs.png – TheGooooogle Apr 12 '18 at 09:52
  • okay add a for loop `for(DataSnapshot datas: dataSnapshot.getChildren()){ String fullname=datas.child("full_name").getValue().toString();` inside the second listener now it will work – Peter Haddad Apr 12 '18 at 09:56
  • Yes the error is gone but still comment1.setUsername(fullname); is username is not working. outputing full name in logcat is working and showing the name. The problem from the first post is comment1.setUsername(fullname); not working inside the second listener and working inside first listener...even comment1.setUsername("sometext"); inside second listener is not working which i think is really strange. But if it is in first listener it works....we are almost back to where we started now – TheGooooogle Apr 12 '18 at 10:16
  • in the second listener write `comment1=new Comment()` – Peter Haddad Apr 12 '18 at 10:18
  • Declaring it inside is giving me, java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.research.xxxxxx.Comment.getUsername()' on a null object reference.....that is on this line String name=getItem(position).getUsername(); – TheGooooogle Apr 12 '18 at 11:04
  • Now my real problem is this https://stackoverflow.com/questions/42140707/retrive-string-out-of-addvalueeventlistener-firebase but sadly so many question but not a single real or full solution. The problem is created by asynchronous nature of listeners.... – TheGooooogle Apr 12 '18 at 16:09
  • I have done nested listeners and it works, if you add the variable outside of the second listener you will get null, this `String fullname=dataSnapshot.child("full_name").getValue().toString();` is working, it is this `comment1.setUsername(fullname);` that is not working – Peter Haddad Apr 12 '18 at 16:13
  • thanks. By the way sorry for the wording above. I meant in that link I sent there are so many questions but not a single real solution. Yes that line is working. But setusername done inside second listeners will obviously won't work and it is like ajax refresh and value is lost and no relation between defined out the second listener and first listeners. So I need someway to get that fullname outside the second event listener. Even I tried it as a global variable, didn't work. – TheGooooogle Apr 13 '18 at 00:15
  • because it is asychronous, it wont work adding it outside of the second listener you will get null there for sure. But why is `setUsername` not working inside the second listener if retrieving `fullname` is working – Peter Haddad Apr 14 '18 at 16:01