Android Studio中Firebase Realtime Database的orderByValue()为何失效?
核心概念:orderByValue()到底依据什么?
orderByValue() 仅针对当前查询节点下的直接子节点的基础类型值(字符串、数字、布尔值)进行排序或筛选。如果直接子节点是复杂对象(比如你的TimeModel实例),Firebase无法将对象解析为可比较的"值",此时该查询会失效。
你的问题拆解
1. 原查询路径下orderByValue()失效,但orderByKey()/orderByChild()正常
假设你的Firebase数据结构是这样的:
users - [userID] - TIMES - [timeId1] - startTime: "2024-05-01" - endTime: "2024-05-02" - [timeId2] - startTime: "2024-05-03" - endTime: "2024-05-04"
当你针对[timeId1]或[timeId2]这类节点用orderByValue()时,当前节点的直接子节点是startTime和endTime,但orderByValue()会尝试把整个TimeModel对象当作"值"来处理——这是不被支持的,因此查询无结果,TextView自然不显示内容。
而orderByKey()是按节点的键(比如timeId1)排序,orderByChild("startTime")是按对象内的startTime属性值排序,这两种查询都符合Firebase的规则,所以能正常工作。
2. 修改路径后能显示时间但无法用equalsTo()
当你把查询路径改为databaseReference.child(userID).child("TIMES").orderByValue(),此时查询的是TIMES节点下的直接子节点(也就是timeId1、timeId2这些对象节点)。Firebase无法对对象执行orderByValue(),但你能看到时间,大概率是遍历快照时误取了节点的键(比如timeId可能包含时间信息)或者其他非预期值,并非正确读取startTime。
这种情况下equalsTo()无法生效,因为它尝试匹配的是整个TimeModel对象的"值"——Firebase不支持对象间的直接比较。
正确的解决方案
如果你要筛选或排序startTime,必须用orderByChild()搭配筛选方法,示例代码如下:
DatabaseReference timesRef = FirebaseDatabase.getInstance().getReference() .child(userID) .child("TIMES"); // 按startTime筛选特定时间的记录 timesRef.orderByChild("startTime") .equalTo("2024-05-01") .addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot timeSnapshot : dataSnapshot.getChildren()) { TimeModel timeModel = timeSnapshot.getValue(TimeModel.class); if (timeModel != null) { // 将startTime设置到TextView yourTextView.setText(timeModel.getStartTime()); } } } @Override public void onCancelled(DatabaseError databaseError) { // 处理查询错误 } });
orderByValue()的正确使用场景
只有当你的节点结构是基础类型的键值对时,orderByValue()才有用,比如:
scores - user1: 90 - user2: 85 - user3: 95
此时scoresRef.orderByValue()可以按分数排序,scoresRef.orderByValue().equalTo(90)能筛选出分数为90的用户。
内容的提问来源于stack exchange,提问作者steeveKA1

