Firebase Realtime Database OR条件查询实现:解决聊天消息对端不可见问题
解决方案
问题根源
Firebase Realtime Database 原生不支持多字段OR查询,你之前的两段代码各自执行时都会清空原有列表,导致只能保留最后一次查询的结果,自然只能实现单端消息可见。
方案1:合并两次查询结果(无需修改数据库结构)
不需要调整现有数据库结构,只需要调整查询逻辑,等待两次查询都完成后合并去重再更新列表即可,示例代码如下:
// 先清空一次列表 chatModels.clear(); // 定义计数器,确保两次查询都完成再刷新UI final int[] queryCount = {0}; // 第一次查询:匹配users/uid字段 FirebaseDatabase.getInstance().getReference().child("chatrooms") .orderByChild("users/uid").equalTo(uid).addListenerForSingleValueEvent(new ValueEventListener(){ @Override public void onDataChange(@NonNull DataSnapshot snapshot) { for (DataSnapshot item : snapshot.getChildren()){ ChatModel1 model = item.getValue(ChatModel1.class); // 去重:避免同一个聊天室同时匹配两个字段重复添加 boolean isExist = false; for(ChatModel1 existModel : chatModels){ // 这里假设ChatModel1有聊天室id字段getRoomId,替换成你实际的id字段名 if(existModel.getRoomId().equals(item.getKey())){ isExist = true; break; } } if(!isExist){ chatModels.add(model); } } queryCount[0]++; if(queryCount[0] == 2){ notifyDataSetChanged(); } } @Override public void onCancelled(@NonNull DatabaseError error) { queryCount[0]++; if(queryCount[0] == 2){ notifyDataSetChanged(); } } }); // 第二次查询:匹配users/sellerUid字段 FirebaseDatabase.getInstance().getReference().child("chatrooms") .orderByChild("users/sellerUid").equalTo(uid).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { for (DataSnapshot item : snapshot.getChildren()){ ChatModel1 model = item.getValue(ChatModel1.class); boolean isExist = false; for(ChatModel1 existModel : chatModels){ if(existModel.getRoomId().equals(item.getKey())){ isExist = true; break; } } if(!isExist){ chatModels.add(model); } } queryCount[0]++; if(queryCount[0] == 2){ notifyDataSetChanged(); } } @Override public void onCancelled(@NonNull DatabaseError error) { queryCount[0]++; if(queryCount[0] == 2){ notifyDataSetChanged(); } } });
方案2:优化数据库结构,单次查询实现(性能更优)
如果聊天室数据量较大,推荐调整数据库结构,在每个聊天室的users节点下新增成员索引字段,结构如下:
"chatrooms" : { "-Mn0ZDpdWsOb8XFFTYmi" : { "comments" : {}, "users" : { "itemName" : "goods", "sellerUid" : "vzTQG0Fb3DgsVKGgGj0R23uL6Hx2", "uid" : "QTC8Msw1n2aUF8mDbTCUNk5k7sH3", // 新增成员索引,将两个uid都作为键,值设为true "memberUids": { "QTC8Msw1n2aUF8mDbTCUNk5k7sH3": true, "vzTQG0Fb3DgsVKGgGj0R23uL6Hx2": true } } } }
调整后只需要一次查询即可拿到所有匹配的聊天室,代码如下:
FirebaseDatabase.getInstance().getReference().child("chatrooms") .orderByChild("users/memberUids/"+uid).equalTo(true) .addListenerForSingleValueEvent(new ValueEventListener(){ @Override public void onDataChange(@NonNull DataSnapshot snapshot) { chatModels.clear(); for (DataSnapshot item : snapshot.getChildren()){ chatModels.add(item.getValue(ChatModel1.class)); } notifyDataSetChanged(); } @Override public void onCancelled(@NonNull DatabaseError error) { } });
需要注意要在Firebase Realtime Database的规则中为users/memberUids字段添加索引,避免查询性能下降。
内容的提问来源于stack exchange,提问作者ym Kim
相关产品推荐
相关产品推荐

