0

I'm trying to get data like SQL left join clause. Here are my nodes sample:

Firebase Database

{
  "teachers": {        
    "nodeKey01": {
      "name":"captain hook",
      "branch":"Math",
    },        
    "nodeKey02": {
      "name":"peter pan",
      "branch":"Science",
    }
  },

  "students": {        
    "nodeKey100": {
      "name"  : "davy jones",
      "teacherKey": "nodeKey01"
    },        
    "nodeKey101": {
      "name"  : "jack sparrow",
      "teacherKey": "nodeKey02"
    },        
    "nodeKey102": {
      "name"  : "salazar",
      "teacherKey": "nodeKey01"
    }
  }  
}

I'd like to query "students" referances and get datas with "teachers" name and branch. I loked documantation and many examples bu didn't figure out. Firebase is not include SQL database languge but there has to be a way/method to join nodes.

Models:

public class Student {    
    private String name;
    private String teacherKey;
    private String key;
    private Teacher teacher;

    public Student() {}

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put(name, name);
        result.put(teacherKey, teacherKey);        
        return result;
    }   

    public String getKey() { return key;}
    public void setKey(String objectKey) { this.key = key; }
    public String getName() { return name;  }
    public void setName(String name) { this.name = name; }
    public String getTeacherKey() { return teacherKey; }
    public void setTeacherKey(String teacherKey) { this.teacherKey = teacherKey; }
    public Teacher getTeacher() { return teacher;  }
    public void setTeacher(Teacher teacher) { this.teacher = teacher; } 
}

public class Teacher {    
    private String name;
    private String branch;
    private String key;

    public Teacher() {}

    @Exclude
    public Map<String, Object> toMap() {
        HashMap<String, Object> result = new HashMap<>();
        result.put(name, name);
        result.put(branch, branch);        
        return result;
    }

    public String getKey() { return key;}
    public void setKey(String objectKey) { this.key = key; }
    public String getName() { return name;  }
    public void setName(String name) { this.name = name; }
    public String getBranch() { return branch; }
    public void setBranch(String branch) { this.branch = branch; }
}

Firebase Query Codes:

public class StudentsFragment extends Fragment {

    List<Students> listData = new ArrayList<>();
    StudentAdapter adapter;
    @BindView(R.id.list)    ListView _list;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_students, container, false);

        ButterKnife.bind(this, view);

        mDatabase = FirebaseDatabase.getInstance().getReference();

        adapter = new StudentAdapter(getActivity(), listData);
        _list.setAdapter(adapter);

        initDatabase();

        return view;
    }

    private void initDatabase() {
        final List<Teacher> teachers = new ArrayList<>();

        Query query1 = mDatabase.child("teachers");

        query1.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                teachers.clear();
                for(DataSnapshot data : dataSnapshot.getChildren()){
                    Teacher item = data.getValue(Teacher.class);
                    item.setKey(data.getKey());
                    teachers.add(item);
                }

                Query query2 = mDatabase.child("students");
                query2.addValueEventListener(new ValueEventListener() {
                    @Override
                    public void onDataChange(DataSnapshot dataSnapshot) {
                        listData.clear();
                        for (DataSnapshot data: dataSnapshot.getChildren()) {
                            AbsentTeacher item = data.getValue(Student.class);
                            item.setKey(data.getKey());
                            item.setTeacher(getTeacherByKey(teachers, item.getTeacherKey()));
                            listData.add(item);
                        }

                        adapter.notifyDataSetChanged();
                    }

                    private Teacher getTeacherByKey(List<Teacher> list, String key) {
                        int index = 0;    
                        for (int i=0;i<list.size();i++){
                            if (list.get(i).getObjectKey().equals(key)) {
                                index = i;
                                break;
                            }
                        }    
                        return list.get(index);
                    }

                    @Override
                    public void onCancelled(DatabaseError databaseError) {}
                });    
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {}
        });
    }
}

It's working but I'm getting joined nodes with two firebase query and "for loop"... And this seems a performance problem.

KENdi
  • 7,576
  • 2
  • 16
  • 31
RedLEON
  • 281
  • 2
  • 7
  • 19
  • Client-side joins for reasonable data sets are not a performance problem, since Firebase pipelines the requests over a single connection. See my explanation (as test code) here: http://stackoverflow.com/questions/35931526/speed-up-fetching-posts-for-my-social-network-app-by-using-query-instead-of-obse/35932786#35932786 – Frank van Puffelen Jul 09 '17 at 15:22
  • Thank you @FrankvanPuffelen. So my way is one of proper? – RedLEON Jul 11 '17 at 14:30
  • That's something you will have to determine for yourself. But client-side joins are normal when using Firebase. There are many ways to implement them, and the right one depends on app use-case and personal preferences. If you really have a performance problem, share details on that specific problem: how many nodes are you loading, how many are you joining, what time does it take, what connection speed, etc. – Frank van Puffelen Jul 11 '17 at 14:34

0 Answers0