具有多个键的Android Firebase查询

具有多个键的Android Firebase查询,android,firebase,firebase-realtime-database,Android,Firebase,Firebase Realtime Database,这种问题已经被提出,有些已经得到了回答。 但是我有一些困惑,这就是为什么我要提出这个问题。在我阅读了Firebase文档“如何从中构造Firebase中的数据”之后,我在谷歌上搜索并试图查询一个用户的组列表(有几天,仍然没有找到解决方案) 假设我们已经拥有用户从/users/{$user\u id}节点参与的组id,并且我们希望通过groupd id列表从/groups获取组详细信息列表。例如,类似下面的查询 SELECT * FROM groups WHERE key = "techpion

这种问题已经被提出,有些已经得到了回答。 但是我有一些困惑,这就是为什么我要提出这个问题。在我阅读了Firebase文档“如何从中构造Firebase中的数据”之后,我在谷歌上搜索并试图查询一个用户的组列表(有几天,仍然没有找到解决方案)

假设我们已经拥有用户从/users/{$user\u id}节点参与的组id,并且我们希望通过groupd id列表从/groups获取组详细信息列表。例如,类似下面的查询

SELECT * FROM groups WHERE key = "techpioneers" AND key = "womentechmakers";
根据谷歌搜索结果和stackoverflow答案,Firebase不支持多where子句。逐个迭代/groups/{$groud_id}节点以获取组详细信息列表也是一种不好的方法


很抱歉问了这么长时间。请帮助我们如何使用Firebase android SDK从Firebase中查询具有多个键的此类数据列表。

Firebase实时数据库的一个缺点是其数据结构不灵活。如果要执行查看不同数据节点的查询,几乎总是需要对数据进行非规范化。这样做的好处是

  • 将数据分解为谨慎的数据块
  • 更好地查询统计数据等
  • 您不必下载大量嵌套数据
  • 缺点是:

  • 您的数据需要多个组合查询,例如
    user by username'或
    
    按用户分组`
  • 这似乎有点复杂和不直观
  • 回到你的问题: 鉴于下表结构:

    group
        group1
            name:"Best group"
            description: "The best group"
        group2:
            name:"An okay group"
            description: "A decent group"
    user
        user1
             name: "User1"
    
        user2
             name: "User2"
    group-by-user
        user1
             group1: true
             group2: true
        user2
             group2: true
    
    请注意,我是如何创建一个新表的,该表将用户与组相关联,而无需将此信息放在用户表中。这确保用户表仅用于基本的非关系用户信息

    要在Java中查询这个问题,它将如下所示

    //Get a reference to groups a user is in
           //get a reference
        DatabaseReference groupByUserRef = FirebaseDatabase.getInstance().getReference();
        //get a reference to the join table mentioned above
        groupByUserRef.child("group-by-user").child("user1").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                //This contains a list of group keys associated to the user;
                Iterable<DataSnapshot> groupsByUser = dataSnapshot.getChildren();
                //iterate through the list of group keys associated to the user
                groupsByUser.forEach(groupDatasnapshot -> {
                    String groupId = groupDatasnapshot.getKey();
                    FirebaseDatabase groupReference;
                    DatabaseReference groupRef = FirebaseDatabase.getInstance().getReference();
    
                    //Once the key has been retrieved, do a search in the database to get the group
                    groupRef.child("group").child(groupId).addValueEventListener(new ValueEventListener() {
                        @Override
                        public void onDataChange(DataSnapshot dataSnapshot) {
                            //Here is where you will get the groups associated to the user.
                            Group group = dataSnapshot.getValue(Group.class);
                            //Add logic here ..
                        }
    
                        @Override
                        public void onCancelled(DatabaseError databaseError) {
    
                        }
                    });
                });
            }
    
            @Override
            public void onCancelled(DatabaseError databaseError) {
    
            }
        });
    
    //获取用户所在组的引用
    //获得推荐信
    DatabaseReference groupByUserRef=FirebaseDatabase.getInstance().getReference();
    //获取对上述联接表的引用
    groupByUserRef.child(“按用户分组”).child(“user1”).addValueEventListener(新的ValueEventListener(){
    @凌驾
    公共void onDataChange(DataSnapshot DataSnapshot){
    //其中包含与用户关联的组密钥列表;
    Iterable groupsByUser=dataSnapshot.getChildren();
    //遍历与用户关联的组键列表
    groupsByUser.forEach(groupDatasnapshot->{
    字符串groupId=groupDatasnapshot.getKey();
    FirebaseDatabaseGroupReference;
    DatabaseReference groupRef=FirebaseDatabase.getInstance().getReference();
    //检索到密钥后,在数据库中进行搜索以获取组
    groupRef.child(“组”).child(groupId).addValueEventListener(新的ValueEventListener()){
    @凌驾
    公共void onDataChange(DataSnapshot DataSnapshot){
    //这里是您将获得与用户关联的组的位置。
    Group Group=dataSnapshot.getValue(Group.class);
    //在这里添加逻辑。。
    }
    @凌驾
    已取消的公共void(DatabaseError DatabaseError){
    }
    });
    });
    }
    @凌驾
    已取消的公共void(DatabaseError DatabaseError){
    }
    });
    
    编辑 总结 如上所述,您可以看到这是一种非常复杂的方法。 这是实时数据库的一个缺点。如果要确保不在密钥上循环,可以使用以下选项

  • 不要对数据进行非规范化,将组信息直接放在
    用户
    表中。这样做的缺点是,当您的群组信息增长时,您必须提取大量数据集(其中一些您不需要)
  • 使用firebase cloud firestore-他们已经设法解决了这里的问题

  • 谢谢你的回答,兄弟@martinomburajr。我希望避免迭代组ID并逐个获取详细信息的过程,兄弟。那么,用一个查询就不可能了吗?嘿,我编辑了我的回答来回答你关于循环键的问题