Firebase Database查询当年WorkDays异常问题求助
问题分析与解决方案
问题根源
你遇到的返回全部WorkDays条目、无法在服务器端过滤的问题,主要有两个原因:
1. 缺少数据库索引
Firebase Realtime Database要求对orderByChild指定的字段创建规则索引,否则查询会在客户端执行——也就是先拉取所有数据再过滤,这不仅浪费带宽,还会让你看到返回全部条目的现象。
2. 查询范围边界错误
你使用endBefore(endDate),其中endDate是${currentYear}-12-31,这个条件会排除postedAtDate恰好等于${currentYear}-12-31的条目,导致范围覆盖不全。
修正步骤
第一步:添加数据库索引
在Firebase控制台的「规则」页面,为Users/{userId}/WorkDays下的postedAtDate字段添加索引,规则示例如下:
{ "rules": { "Users": { "$userId": { "WorkDays": { ".indexOn": "postedAtDate" } } } } }
添加索引后,Firebase服务器才会帮你在端上完成过滤,不会拉取全部数据。
第二步:修正查询范围
把endBefore(endDate)改成endAt("${currentYear + 1}-01-01"),这样可以包含当年12月31日的所有数据,同时正确截止到下一年的第一天之前。修正后的函数代码:
fun getWorkDays(mAuth: FirebaseAuth) { viewModelScope.launch { val user = mAuth.currentUser val userId = user!!.uid val currentYear = Calendar.getInstance().get(Calendar.YEAR) val startDate = "$currentYear-01-01" // 修正截止日期,包含当年12月31日的所有数据 val endDate = "${currentYear + 1}-01-01" val reference = FirebaseDatabase.getInstance().getReference("Users").child(userId) .child("WorkDays") reference.orderByChild("postedAtDate") .startAt(startDate) .endAt(endDate) // 替换endBefore为endAt .addListenerForSingleValueEvent(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val workDays = mutableListOf<WorkDay>() for (postSnapshot in snapshot.children) { postSnapshot.getValue(WorkDay::class.java)?.let { workDays.add(it) } } this@ReportsViewModel._workDays.value = ArrayList(workDays) } override fun onCancelled(error: DatabaseError) { _errorMessage.postValue(error.message.toString()) } }) } }
额外优化
- 避免使用
!!强制非空,改用?.let做安全处理,减少空指针风险 - 可以直接用
LocalDate.now().year替代Calendar获取当前年份(Android API 26+可用,低版本需引入ThreeTenABP扩展库)
内容的提问来源于stack exchange,提问作者Faris Rizvanović
相关产品推荐
相关产品推荐

