如何比较Android Firebase中来自不同引用的两个子节点?

时间:2019-06-09 09:30:21

标签: java android firebase firebase-realtime-database

在Firebase中,我有一个“用户”节点,用于存储有关注册用户的信息,而我有一个“任务”节点,其中包含由每个用户创建的任务信息以及3个手动添加到这些任务的所有者电子邮件地址。我正在尝试将“用户”的电子邮件字段与每个所有者的电子邮件进行比较。如果当前用户的电子邮件是3个所有者电子邮件之一,那么我将仅显示他的电子邮件在其中的任务。

这是我的Firebase实时数据库的摘录:

    "Users" : 
       {"SolD4tqjUJd1Xru3mRliwtoik2A3" : 
           { "email" : "x@gmail.com",

             "id" : "SolD4tqjUJd1Xru3mRliwtoik2A3",

            "name" : "AB",

            "phone" : "123456789"
           }
        },


     "tasks" : 
         { "-LgrtyuTjd2QpNIhUeEi" : 
              { "-Lgsjx1c-E6OU3t1SbhL" : 
                   { "id" : "-Lgsjx1c-E6OU3t1SbhL",

                     "owner_one" : "x@gmail.com",

                    "owner_three" : "y@gmail.com",

                    "owner_two" : "z@gmail.com",

                    "projectId" : "-LgrtyuTjd2QpNIhUeEi",

                    "taskDate" : "2019 / 6 / 5",

                    "taskDescription" : "dddd",

                    "taskName" : "ddddd",

                    "taskstatus" : "Closed",

                    "userId" : "SolD4tqjUJd1Xru3mRliwtoik2A3"
                  }
                }
               }
              }

我尝试使用以下代码从“用户”获得电子邮件,而从任务中获得所有者的电子邮件,但是我被困在将电子邮件与电子邮件1,电子邮件2和电子邮件3进行比较。

        myTasks = findViewById(R.id.myTasks);
        myTasks.setLayoutManager(new LinearLayoutManager(this));
        tasks = new ArrayList<>();

        UsersRef = FirebaseDatabase.getInstance().getReference().child("Users");
    UsersRef.child(currentUserID).addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            User user = dataSnapshot.getValue(User.class);
            String email = user.getEmail();
        }

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

        }
    });


    reference = FirebaseDatabase.getInstance().getReference().child("tasks");
    reference.addChildEventListener(new ChildEventListener(){


        @Override
        public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
            //set code to retrieve data and replace layout

            for(DataSnapshot dataSnapshot1: dataSnapshot.getChildren()){
                Task p;
                p = dataSnapshot1.getValue(Task.class);
                String email1 = p.getOwner_one();
                String email2 = p.getOwner_two();
                String email3 = p.getOwner_three();

                tasks.add(p);
            }
            taskAdapter = new TaskAdapter(MyTasks.this, tasks);
            myTasks.setAdapter(taskAdapter);
            taskAdapter.notifyDataSetChanged();
        }

1 个答案:

答案 0 :(得分:0)

无需为了获取用户的电子邮件地址而创建数据库调用,您可以像这样直接从FirebaseUser对象中直接获取电子邮件地址:

String email = FirebaseAuth.getInstance().getCurrentUser().getEmail();

根据您的数据库架构,请注意,当您有两个具有动态(推入)名称的节点时,无法查询数据库。 Firebase中也没有通配符。为了解决这个问题,您应该通过添加项目的ID作为任务对象的属性来减少子级数。现在,要获取与特定电子邮件地址相对应的所有任务,请使用以下查询:

reference = FirebaseDatabase.getInstance().getReference().child("tasks");
Query firstQuery = reference.orderByChild("owner_one").equalsTo("x@gmail.com");

这仅适用于一个属性。不幸的是,您不能使用多个“ WHERE”子句(以SQL术语)在Firebase实时数据库中查询。您可以做的是查询数据库三次,每个所有者属性一次。第二和第三个查询应如下所示:

Query secondQuery = reference.orderByChild("owner_two").equalsTo("x@gmail.com");
Query thirdQuery = reference.orderByChild("owner_three").equalsTo("x@gmail.com");

请注意,为了获得理想的结果,您应该使用如下所示的嵌套查询:

ChildEventListener childEventListener = new ChildEventListener() {
    @Override
    public void onChildAdded(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {
        if(dataSnapshot.exists()) {
            //Perform the second query and then the third query
        }
    }

    @Override
    public void onChildChanged(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {}

    @Override
    public void onChildRemoved(@NonNull DataSnapshot dataSnapshot) {}

    @Override
    public void onChildMoved(@NonNull DataSnapshot dataSnapshot, @Nullable String s) {}

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {}
};
firstQuery.addChildEventListener(childEventListener);

但是,这可以在Cloud Firestore中更轻松地完成,在这里您可以添加类型array的属性并使用whereArrayContains()方法,如下所示:

tasksRef.whereArrayContains("owners", "x@gmail.com");