Firebase实时数据库如何在没有密钥的情况下获取子记录

Posted

技术标签:

【中文标题】Firebase实时数据库如何在没有密钥的情况下获取子记录【英文标题】:Firebase realtime database how to get a child record without the key 【发布时间】:2021-11-26 05:25:34 【问题描述】:

我有一个带有“用户”节点的 Firebase 数据库,该节点有一些子节点,我想检索特定用户的“类型”字段,但我不知道该用户的密钥是什么。我有以下数据结构:

users
    -MlHrU3_UgMzrU3IpfOW
       email: 
          "mail@gmail.com"
       tipo: 
           "Aluno"

我尝试这样做,但它总是返回 null

final String[] tipoUserBD = new String[1];
    database = FirebaseDatabase.getInstance().getReference("users");
    database.addValueEventListener(new ValueEventListener() 
        @Override
        public void onDataChange(@NonNull DataSnapshot snapshot) 
            list.clear();
            for(DataSnapshot dataSnapshot : snapshot.getChildren())
                if(dataSnapshot.child("email").getValue(String.class).equals(user.getEmail())) 
                    tipoUser[0] = dataSnapshot.child("tipo").getValue().toString();
                
            
        

        @Override
        public void onCancelled(@NonNull DatabaseError error) 

        
    );

【问题讨论】:

"我想检索特定用户的“类型”字段" 您对特定用户了解多少?如果你对他们一无所知,你能做的最好的就是阅读所有用户。 【参考方案1】:

如果您知道用户的密钥(我知道您不知道,但我们假设您在其他情况下知道),您可以阅读他们的个人资料并记录他们的类型:

database = FirebaseDatabase.getInstance().getReference("users");
database.child("-MlHrU3_UgMzrU3IpfOW").addValueEventListener(new ValueEventListener() 
         // ? use the key here
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) 
        Log.d("Tipo", dataSnapshot.child("tipo").getValue(String.class)); // ? Specify type here
    

    @Override
    public void onCancelled(@NonNull DatabaseError error) 
        throw error.toException(); // ? never ignore errors
    
);

如果您知道一些标识用户的属性,但不知道键,您可以使用查询来查找匹配的节点:

database = FirebaseDatabase.getInstance().getReference("users");
database.orderByChild("email").equalTo("mail@gmail.com").addValueEventListener(new ValueEventListener() 
         // ? use the property name and value here
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) 
        for(DataSnapshot dataSnapshot : snapshot.getChildren())
            Log.d("Tipo", dataSnapshot.child("tipo").getValue(String.class)); // ? Specify type here
        
    

    @Override
    public void onCancelled(@NonNull DatabaseError error) 
        throw error.toException(); // ? never ignore errors
    
);

如果您对用户一无所知,最好的办法就是遍历所有用户:

database = FirebaseDatabase.getInstance().getReference("users");
database.addValueEventListener(new ValueEventListener() 
    @Override
    public void onDataChange(@NonNull DataSnapshot snapshot) 
        for(DataSnapshot dataSnapshot : snapshot.getChildren())
            Log.d("Tipo", dataSnapshot.child("tipo").getValue(String.class)); 
        
    

    @Override
    public void onCancelled(@NonNull DatabaseError error) 
        throw error.toException(); // ? never ignore errors
    
);

您尝试使用 tipoUser[0] 的技巧是一种反模式,因为这通常意味着您忽略了异步加载的数据。

作为一般(和硬性)规则:任何需要数据库数据的代码都需要内部 onDataChange 或从那里调用。

有关这方面的更多信息和示例,请参阅:

getContactsFromFirebase() method return an empty list

Setting Singleton property value in Firebase Listener

【讨论】:

它可以在日志中打印用户的类型,但是当我将此值分配给字符串类型的变量时,应用程序会给出一个错误,好像该变量为空:( 在没有看到代码和错误的情况下有点难以确定,但我的猜测是您仍在尝试使用onDataChange/onDataChange 之外的数据库中的数据已经跑了。我的答案的最后一部分解释了为什么这不起作用,并且链接显示了更多关于此的内容 - 以及如何在 onDataChange 中实现代码或使用回调。

以上是关于Firebase实时数据库如何在没有密钥的情况下获取子记录的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 ASP.NET MVC 应用程序在 firebase 实时数据库中设置数据

关于使用android studio在firebase实时数据库中的uid下创建随机密钥

我可以在没有实时数据库的情况下访问 Firebase 存储吗

如何在不在 firebase 实时数据库上生成 firebase id 的情况下发布我的数据?

如何仅在 Firebase 中获取子密钥

如何对firebase自动生成的密钥进行排序?