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

标签 java android firebase firebase-realtime-database

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

这是我的 Firebase 实时数据库的 fragment :

    "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"
                  }
                }
               }
              }

我已尝试使用以下代码来获取来自用户的电子邮件和来自任务的所有者电子邮件,但我无法将电子邮件与 email1、email2 和 email3 进行比较。

        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();
        }

最佳答案

无需创建数据库调用即可获取用户的电子邮件地址,您可以直接从 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 实时数据库中进行查询。您可以做的是查询数据库三次,每个所有者属性(property)一次。第二个和第三个查询应如下所示:

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");

关于java - 如何比较 Android Firebase 中不同引用的两个子节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56513461/

相关文章:

java - 使用 JNI 从 C++ 调用 JAVA 方法,无参数

java - 将 XML 注释添加到编码文件中

java - 是否有一种可以在格式之间动态转换的模式?

javascript - 使用 ControllerAs 语法的 Firebase 3 向数据绑定(bind)

java - 使用 Firebase-UI (Android) 的 Firestore 聊天应用

javascript - 如何解决 Reactjs 和 Firebase Google Cloud Firestore 中发生的此错误?

java - 如何调用scanDouble()方法?

android - FusedLocationApi.getLastLocation 始终为空

android - 生成APK错误:ExecutionException aapt.v2.Aapt2InternalException

java - 如何将上传到云存储的图片调整为指定大小?