0

How can I change the naming of the nodes of my children in the image below? questions_stats is a List<Integer>, I'm aware that I get integers as nodes Id because this is a List. I create each of the children randomly with a number between 0 and 1000. I set this ID as part of the object and to find it I loop trough the list. What I want is to set the "0671" as the Key of the Object at the moment I create it.

How should I define my object in order to access each child with an Id that I define as a String.

Each of the questions_stats is an object.

This is my UserProfile Class definition.

public class UserProfile implements Parcelable {
    private List<Integer> questions_list;
    private List<QuestionsStats> questions_stats;
    private String country_name, share_code, user_name;
    private int token_count;
    private Boolean is_guest;

    public UserProfile() {
    }

    public UserProfile(List<Integer> questions_list, List<QuestionsStats> questions_stats, String country_name, String share_code, String user_name, int token_count, Boolean is_guest) {
        this.questions_list = questions_list;
        this.questions_stats = questions_stats;
        this.country_name = country_name;
        this.share_code = share_code;
        this.user_name = user_name;
        this.token_count = token_count;
        this.is_guest = is_guest;
    }
 }

I know I can set them using the child("0159").setValue(QuestionStats) individually.

But for my purpose I need to retrieve the data of the "user" as a whole and then iterate whithin questions_stats like it is a List.

How should I define my UserProfile class in order to achieve what I want?

Anybody could give me a hint?

Sample

Guanaco Devs
  • 1,822
  • 2
  • 21
  • 38
  • @Peter Haddad questions_stats is a List of Objects, since is a List 0 and 1 are indexes. What I want is to be able to set a key like "0001" or "8760" to I'd a specific object and access questions_stats as a Map instead of a list. I can access a specific object within the list by using a four loop, but using a Map would make it more efficient I believe. Don't know how to implement the Map. – Guanaco Devs Nov 18 '17 at 08:10
  • `Firebase` database is a NoSQL database which is structured as pairs of key and veales, which means that every node in the database is a `Map`. Seeing your database screenshot, `question_stats` is also a `Map`, with has `question_stats` as a key and data beneath it as a value. `0` node is also a map, which the `0` as a key, and the data beneath it as a value. And so on. Don't be confused that you have a list in your model class. Inside the database every node is a `Map`. – Alex Mamo Nov 18 '17 at 08:17

2 Answers2

0

How can I change the node names of my children in the image below?

Answer: There is no way in which you can change the names of the nodes from your Firebase database. There is no API for doing that. What can you do instead is to attach a listener on that node and get the dataSnapshot object. Having that data, you can write it in another place using other names. You cannot simply rename them from 0 to 0000, 1 to 0001 and so on.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • I believe there is a way using Map to set the name. I just don't know how to implement it in my model. Don't want to rename, I want to set the Key(node name) when I update my "user". – Guanaco Devs Nov 18 '17 at 08:03
  • Even if are using `Map`, you cannot simply change the name of a node. And this is not about your model, it'a about Firebase that does not provide any tool that allow you to rename a node. When you want to set the key (node key), it means that you want to update that key, which is not possible in Firebase. The single way in which you can achieve this, it is as i mentoned above. Get the data from current location, write it in another location using another name, delete the record from the old location. – Alex Mamo Nov 18 '17 at 08:10
  • don't want to rename, as it is the node ID is an index, because questions_stats is a List. What I want is that the first time I create a node whitin name it with a String so I can access it later to modify it's content. Once I create it I don't need to rename it. I retrieve user as a whole manipulate its data and update it. I can work it as it is with a For loop, but I don't believe it is efficient. – Guanaco Devs Nov 18 '17 at 08:21
  • You can work also as it is. I cannot see efficiency problem. This is how Firebase works. That's no problem with your code, nor with your database. You can go ahead with it. – Alex Mamo Nov 18 '17 at 08:24
  • Eventually I will have more than 500 nodes under questions_stats. Knowing the name of the value I want to access I think it'll be better than iterating trough the list. If I randomly select an object "6791" and add it in my empty questions_stats List it'll place it in the index 0. Instead I want to Key it with "6791" from the time I add it – Guanaco Devs Nov 18 '17 at 08:37
  • You are not iterating through a list in the first place. You are interating through a `dataSnapshot` object, then your a getting the data and add it to a list. Having that list, you can do what you want with it. This how things work in Firebase. You interate the list, right after you got the data. You cannot iterate directly. You first need to get the data. And as mentioned above, you get the from the `Map` and add it to a `List`. – Alex Mamo Nov 18 '17 at 08:48
  • that's what I'm doing. I get my user with a snapshot to a UserProfile.class. Then I use my getQuestionsStats() method to access the list(which firebase recognizes as a List, after it deserialize my UserProfile Class ) and operate on it. – Guanaco Devs Nov 18 '17 at 08:58
  • And what is the problem with it? Whant can you not achieve? – Alex Mamo Nov 18 '17 at 09:00
  • I can do what I need. Just think that there should be a better more efficient way. – Guanaco Devs Nov 18 '17 at 09:03
  • There is not. You are doing in a right way. It's a common pratice within Firebase. Keep going with that. – Alex Mamo Nov 18 '17 at 09:19
0

Perhaps I should have asked for How to "Set" the node Id instead of "Change" What I have is an List<QuestionsStats>, but when using an List<QuestionsStats> you get indexes as Keys, What I want is to have the same List<QuestionsStats> but instead of indexes, String Keys for each of my items. So I changed my List for a Map<String, QuestionsStats>. Now the tricky part is when parceling the Object. You can use readMap() or writeMap() to parcel as shown here in this answer by @David Wasser, but it gives a warning:

Please use writeBundle(Bundle) instead. Flattens a Map into the parcel at the current dataPosition(), growing dataCapacity() if needed. The Map keys must be String objects. The Map values are written using writeValue(Object) and must follow the specification there. It is strongly recommended to use writeBundle(Bundle) instead of this method, since the Bundle class provides a type-safe API that allows you to avoid mysterious type errors at the point of marshalling.

So with the help of the comments in This Question I parceled using this code, note that I'm leaving the "easy" way commented in case somebody find it useful or have any comment on that :

    protected UserProfile(Parcel in) {
//        in.readMap(myMap, Object.class.getClassLoader());
        myMap = new HashMap<>();
        String[] array = in.createStringArray();
        Bundle bundle = in.readBundle(Object.class.getClassLoader());
        for (String s : array) {
            myMap.put(s, (Object) bundle.getParcelable(s));
        }
    }


    @Override
    public void writeToParcel(Parcel dest, int flags) {


    //        dest.writeMap(myMap);
            Bundle bundle = new Bundle();
            for (Map.Entry<String, Object> entry : myMap.entrySet()) {
                bundle.putParcelable(entry.getKey(), entry.getValue());
            }
            Set<String> keySet = myMap.keySet();
            String[] array = keySet.toArray(new String[keySet.size()]);
            dest.writeStringArray(array);
            dest.writeBundle(bundle);
        }

Why I want this, well at the moment my list contains less than 100 items but it could grow up to a 1000, I'm no Pro, but I believe that if I already know the key of the item I'm interested in will be always better than having to iterate over the list to find it. In the end my main problem was the usage of a Map, I did not know howto.

Guanaco Devs
  • 1,822
  • 2
  • 21
  • 38