Home > Software engineering >  Accessing nested nodes in a Firebase RTDB, using Flutter
Accessing nested nodes in a Firebase RTDB, using Flutter

Time:04-21

I've got a database that stores user information such as their name and all their friends. The DB look something like this:

{
  "users": {
    "userID here": {
      "bio": "",
      "country": "",
      "dateOfBirth": "2022-04-13 17:49:45.906226",
      "emergencyContacts": {
        "mom": {
          "emailAdd": "[email protected]",
          "name": "mom",
          "phoneNumber": "07492017492",
          "picUrl": "url here'"
        }
      },
      "friends": {
        "auto-generated ID (used push method)": {
          "country": "",
          "profilePicUrl": "url here",
          "userID": "userID here",
          "username": "newOne"
        }
      },
      "fullName": "name",
      "gender": "Female",
      "hobbies": "[]",
      "knownMH": "[]",
      "lastMessageTime": "2022-04-14 08:44:40.639944",      
  }
}

I would like to access the "friends" node. While doing so, I'd also like to store the data in a 2d array. So, each sub-array will contain the data about the user we're currently looping through and one of their friends. This should happen until we've looped through all of the user's friends and then move on to the next user.

It's also worth mentioning; I've used a push method for adding friends so I get randomly assigned keys for the nodes.

I've used the method below, but it's not working, it's returning the wrong list of friends and not looping through all users. Please find the code that I've used below (any help is much appreciated):

  void _retrieveAllFriendships() {
    final allUsersDb = FirebaseDatabase.instance.ref().child('users');
    _allUserssStream = allUsersDb.onValue.listen((event) {
      if (event.snapshot.exists) {
        final data = new Map<dynamic, dynamic>.from(
            event.snapshot.value as Map<dynamic, dynamic>);

        data.forEach((key, value) {
          allUsersDb.child(key).onValue.listen((event) {
            final acc = new Map<dynamic, dynamic>.from(
                event.snapshot.value as Map<dynamic, dynamic>);

            final username = acc['username'] as String;
            final profilePicUrl = acc['profilePicUrl'] as String;
            final country = acc['country'] as String;
            final userID = acc['userID'] as String;

            user = new FriendSuggestionModel(
              picture: profilePicUrl,
              name: username,
              location: country,
              userID: userID,
            );

            _friendshipStream = allUsersDb
                .child(userID)
                .child("friends")
                .onValue
                .listen((event) {
              if (event.snapshot.exists) {
                final data = new Map<dynamic, dynamic>.from(
                    event.snapshot.value as Map<dynamic, dynamic>);

                data.forEach((key, value) {
                  allUsersDb
                      .child(userID)
                      .child("friends")
                      .child(key)
                      .onValue
                      .listen((event) {
                    final friend = new Map<dynamic, dynamic>.from(
                        event.snapshot.value as Map<dynamic, dynamic>);

                    final username = friend['username'] as String;
                    final profilePicUrl = friend['profilePicUrl'] as String;
                    final country = friend['country'] as String;
                    final userID = friend['userID'] as String;

                    friendModel = new FriendSuggestionModel(
                        picture: profilePicUrl,
                        name: username,
                        location: country,
                        userID: userID);
                    List<FriendSuggestionModel> friendship = [
                      user,
                      friendModel
                    ];
                    allFriendships.add(friendship);

                    setState(() {
                      for (int i = 0; i < allFriendships.length; i  ) {
                        print(
                            "${allFriendships[i][0].name} is friends with: ${allFriendships[i][1].name}");
                      }
                    });
                  });
                });
              }
            });
          });
        });
      }
    });
  }

CodePudding user response:

When you attach a listener to allUsersDb.onValue all data under that path is already present in the event.snapshot and you don't need any more listeners for that data.

If you know the name of a child snapshot you want to access, you can get this by snapshot.child("friends"). If you don't know the name of the child snapshots, you can loop over all of them with snapshot.children.forEach.

  • Related