Android中Firebase实时数据库数组内对象的排序查询问题
Firebase实时数据库数组查询问题解决办法
核心原因
Firebase Realtime Database不支持直接查询数组内部的对象属性。当role1是数组时,数组的子节点是数字索引(0、1、2...),你使用的orderByChild("partner_roles/role1/locality")会尝试查找每个partner节点下partner_roles/role1/locality这个直接路径的属性,但实际数组中每个对象的locality路径是partner_roles/role1/0/locality、partner_roles/role1/1/locality,路径不匹配导致查询返回空结果。而当role1是单个对象时,路径partner_roles/role1/locality是有效的,所以能正常返回数据。
推荐解决方案:调整数据结构
将数组改为**键值对(对象)**存储,用唯一ID(比如Firebase自动生成的push ID)代替数组索引,让每个role对象成为role1的直接子节点。
调整前的数据结构
"partners": { "partner_001": { "partner_roles": { "role1": [ {"locality": "location1", "name": "角色A"}, {"locality": "location2", "name": "角色B"} ] } } }
调整后的数据结构
"partners": { "partner_001": { "partner_roles": { "role1": { "role_push_id_1": {"locality": "location1", "name": "角色A"}, "role_push_id_2": {"locality": "location2", "name": "角色B"} } } } }
调整后的查询代码(Android)
DatabaseReference partnersRef = FirebaseDatabase.getInstance().getReference("partners"); partnersRef.orderByChild("partner_roles/role1/locality").equalTo("location2") .addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { for (DataSnapshot partnerSnapshot : snapshot.getChildren()) { // 处理符合条件的partner数据 String partnerId = partnerSnapshot.getKey(); // 可以进一步获取对应的role对象 DataSnapshot role1Snapshot = partnerSnapshot.child("partner_roles/role1"); for (DataSnapshot roleSnapshot : role1Snapshot.getChildren()) { if ("location2".equals(roleSnapshot.child("locality").getValue(String.class))) { // 处理匹配的role数据 } } } } @Override public void onCancelled(@NonNull DatabaseError error) { // 处理查询错误 } });
折中方案(不推荐,效率低)
如果暂时无法修改数据结构,可以先获取所有partner数据,再手动遍历数组筛选符合条件的项:
DatabaseReference partnersRef = FirebaseDatabase.getInstance().getReference("partners"); partnersRef.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { for (DataSnapshot partnerSnapshot : snapshot.getChildren()) { DataSnapshot role1ArraySnapshot = partnerSnapshot.child("partner_roles/role1"); if (role1ArraySnapshot.exists()) { // 遍历数组中的每个role对象 for (DataSnapshot roleSnapshot : role1ArraySnapshot.getChildren()) { String locality = roleSnapshot.child("locality").getValue(String.class); if ("location2".equals(locality)) { // 找到符合条件的项,处理数据 } } } } } @Override public void onCancelled(@NonNull DatabaseError error) { // 处理错误 } });
内容的提问来源于stack exchange,提问作者Mubashir P A
相关产品推荐
相关产品推荐

