简体   繁体   中英

How to read child nodes without mentioning parent node in firebase database within android studio?

I am making an android app using the firebase Realtime database. My rules structure is given below:

{
// Allow anyone to read data, but only authenticated content owners can
// make changes to their data

  "rules": {
    "Users": {
      "$uid": {
        ".read": true,
        // or ".read": "auth.uid != null" for only authenticated users
        ".write": "auth.uid == $uid"
      }
    }
  }
}

It means that a user should be signed in as an authenticated user to write some data. But when it comes to read no sign in is required.

Now I need to ignore the uid of the user to give free access to other users( ie without signing in). 在此处输入图像描述

This is the java code I am using currently to read data.

final Intent k = getIntent();
        final String school = Objects.requireNonNull(k.getExtras()).getString("School");
        final Intent i = getIntent();
        final String roll = Objects.requireNonNull(i.getExtras()).getString("Roll");
 myRef = myfire.getReference("Users")
.child("GcZoeK7JIbNWVOog6ZjUPiBfxwn2")// **I have problem here.**
.child(school).child(roll);
        myRef.child("basic").addValueEventListener(new ValueEventListener() {

            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                String name = (String) dataSnapshot.child("fb01name").getValue().toString();

                String number = (String) dataSnapshot.child("fb04roll").getValue().toString();

                if(name == null){

                    Toast.makeText(getApplicationContext(),"Invalid",Toast.LENGTH_SHORT).show();
                }

                basic model = new basic(name,number);
                tvName.setText(name);

                tvRoll.setText(number);



            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }

        });

I could not decide what to write instead of the first child to read any data without signing in.

.child("GcZoeK7JIbNWVOog6ZjUPiBfxwn2")

Please guide me How to ignore this child? Any help will be appreciated.

EDIT The advice "try to refrain from using deeply nested children" by @Abdullah Z Khan further provided me insight into the problem. I changed my codes as given below:

 myfire = FirebaseDatabase.getInstance();
        final Intent k = getIntent();
        final String school = Objects.requireNonNull(k.getExtras()).getString("School");
        final Intent i = getIntent();
        final String roll = Objects.requireNonNull(i.getExtras()).getString("Roll");
        
//--------------------the trick----------------

        if (school.equals("224613")){
             tvSchool.setText("GcZoeK7JIbNWVOog6ZjUPiBfxwn2");
        }else if (school.equals("224614")){
             tvSchool.setText("uQx5jDVRp9PV3QpM2FBU6HPq5SJ3");
        }
        final String uid = tvSchool.getText().toString();
//---------------------------------------------------
        myRef = myfire.getReference("Users").child(uid).child(roll);
        myRef.child("basic").addValueEventListener(new ValueEventListener() {

            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                String name = (String) dataSnapshot.child("fb01name").getValue().toString();

                String number = (String) dataSnapshot.child("fb04roll").getValue().toString();

                if(name == null){

                    Toast.makeText(getApplicationContext(),"Invalid",Toast.LENGTH_SHORT).show();
                }

                basic model = new basic(name,number);
                tvName.setText(name);

                tvRoll.setText(number);



            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }

        });

Although this PLAN B has temporarily relieved me a bit yet the question is still unanswered.Beacuse I have to write the uid code of users each time they join the app( and have to update and publish the app again and again.A better solution is awaited.

EDIT: Added values in >>> marked lines for understanding

From what is given, this is your database structure:

{
    "uid": {
        "schoolId": {
            "roll": {

            }
        }
    }
}

Because it is so much nested (I'd suggest a different hierarchy altogether), there is no easy way to access a child with an unknown parent as is. However, if you can change the database structure to this:

{
    >>> "224614":"GcZoeK7JIbNWVOog6ZjUPiBfxwn2",
    "schoolId2":"uid2",
    >>> "GcZoeK7JIbNWVOog6ZjUPiBfxwn2": {
        "224614": {
            "roll": {

            }
        }
    }
}

You'll get a uid lookup table. You can then use that to reach the node. Keep in mind this isn't a direct answer to what you asked, which is how to get a nested node(not value) without knowing the parent, but here you can dynamically access uids of whatever school is needed, assuming each school has exactly one parent.

After that, nest your listener:

myRef = myfire.getReference("Users");
myRef.child(school).addValueEventListener(new ValueEventListener() {

            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                if  (dataSnapshot.exists()) {
                    String uid=dataSnapshot.getValue(String.class);
                    myRef.child(uid)// **I have problem here.**
                    .child(school).child(roll);
                            myRef.child("basic").addValueEventListener(new ValueEventListener() {

                                @Override
                                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                                    String name = (String) dataSnapshot.child("fb01name").getValue().toString();

                                    String number = (String) dataSnapshot.child("fb04roll").getValue().toString();

                                    if(name == null){

                                        Toast.makeText(getApplicationContext(),"Invalid",Toast.LENGTH_SHORT).show();
                                    }

                                    basic model = new basic(name,number);
                                    tvName.setText(name);

                                    tvRoll.setText(number);



                                }

                                @Override
                                public void onCancelled(@NonNull DatabaseError error) {

                                }

                            });
                }

            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }

        });

In practice, try to refrain from using deeply nested children, rather use references to other nodes.

I hope this helps!!

how about this:

final Intent k = getIntent();
    final String school = Objects.requireNonNull(k.getExtras()).getString("School");
    final Intent i = getIntent();
    final String roll = Objects.requireNonNull(i.getExtras()).getString("Roll");
    myRef = myfire.getReference("Users")
    
    myRef.addValueEventListener(new ValueEventListener() {

        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            String name = (String) dataSnapshot.child(school).child(roll).child("basic").child("fb01name").getValue().toString();

            String number = (String) dataSnapshot.child(school).child(roll).child("basic").child("fb04roll").getValue().toString();

            if(name == null){

                Toast.makeText(getApplicationContext(),"Invalid",Toast.LENGTH_SHORT).show();
            }

            basic model = new basic(name,number);
            tvName.setText(name);

            tvRoll.setText(number);



        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {

        }

    });

Well, I don't know if I understood your question, but if you are trying to read the children of all the nodes without specifying them, you can try to do something like the code below: (I didn't test it, I just changed your sample)

    myRef = myfire.getReference("Users");
    myRef.addValueEventListener(new ValueEventListener() {

        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

            for (DataSnapshot keySnap : dataSnapshot.getChildren()) {
                for (DataSnapshot schoolSnap : keySnap.getChildren()) {
                    for (DataSnapshot rollSnap : schoolSnap.getChildren()) {
                        String mRollSnap = rollSnap.getKey();

                        String name = mRollSnap.child("basic").child("fb01name").getValue().toString();
                        String number = (String) mRollSnap.child("basic").child("fb04roll").getValue().toString();
                        if(name == null){
                            Toast.makeText(getApplicationContext(),"Invalid",Toast.LENGTH_SHORT).show();
                        }
                        basic model = new basic(name,number);
                        tvName.setText(name);
                        tvRoll.setText(number);

                    }
                }
            }
        }
        @Override
        public void onCancelled(@NonNull DatabaseError error) { }
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM