我在Firestore数据库上有如下任务集合:
"tasks": {
v8NC4GovVOPe21fhwtp0 : {
id: "v8NC4GovVOPe21fhwtp0"
status: 0
dateFrom: 30 april 2019 at 00:00:00 UTC-3
dateTo: 05 may 2019 at 00:00:00 UTC-3
....
},
v7NC4GaxVOPe48ftstp1 : {
id:"v7NC4GaxVOPe48ftstp1"
status: 0
dateFrom: 29 april 2019 at 00:00:00 UTC-3
dateTo: 02 may 2019 at 00:00:00 UTC-3
....
}
}
该文档有一个dateFrom
字段,它指示用户可以开始执行该任务的第一个日期;还有一个dateTo
字段,它指示用户必须完成该任务的最后一天。
我正尝试获取2019年4月以来的所有任务,这意味着dateFrom
或dateTo
属于本月/年的任务(在本示例中,如果月份为2019年4月,它必须提取两个任务)。
在Android上,我得到了所选月份的第一个日期(startDate
),并得到了所选月份的最后一个日期(endDate
),我正在尝试执行以下操作:
val missionsCollection = FirebaseFirestore.getInstance()
.collection("/users").document(uid).collection("tasks")
.whereGreaterThanOrEqualTo("dateFrom", startDate).whereLessThanOrEqualTo("dateTo", endDate)
但是我得到一个错误,说All where filters other than whereEqualTo() must be on the same field. But you have filters on 'dateFrom' and 'dateTo'
。
我考虑过一些解决方法,但是它们看起来都很糟糕,即使我找不到很好的解决方案,我也肯定有一个解决方法。
答案 0 :(得分:1)
Firestore允许链接多个“ where()”方法以创建更特定的查询,但只能在同一字段上。正如您可能在Query limitations的官方文档中看到的那样:
Cloud Firestore不支持以下类型的查询:
- 如上一节所述,在不同字段上具有范围过滤器的查询。
因此,禁止在不同字段上使用范围过滤器。
要实现所需的功能,您需要查询两次数据库,一次是通过调用以下内容来拟合数据:
.whereGreaterThanOrEqualTo("dateFrom", startDate)
第二次使用以下呼叫:
.whereLessThanOrEqualTo("dateTo", endDate)
但是很遗憾,您不能在同一查询中使用它们。
编辑:
在设计数据库架构时,基本上我们为查询构造了架构。因此,除了上述解决方案(您可以在查询中的一个字段上以及客户端代码中的另一个字段上进行过滤)之外,还有另一种方法可以将两个范围的值组合到一个单独的字段中通过某种方式可以使您的用例只有一个字段。
到目前为止,我见过的最成功的示例之一是Geohashes
中使用的组合来过滤经纬度,如下面的视频中Frank Frank Puffelen所述:
了解这两种解决方案在工作量上的差异后,建议您使用第一种解决方案。
还有第三种解决方案,您应该将Mar-Apr中的所有任务添加到单个集合中。然后,您可以使用以下命令查询此新收藏集:
db.collection("tasks-aps-mar")
.whereGreaterThanOrEqualTo("day", 1)
.whereLessThanOrEqualTo("day", 30);
甚至更通用的解决方案是将每个月的任务存储在一个集合中,然后执行查询以获取与所需月份相对应的所有任务。在您的用例中,应该查询数据库以获取每个集合tasks-mar-2019
,tasks-apr-2019
,tasks-may-2019
等中的文档。
关于您的评论,使用数组对您完全没有帮助,因为您不能使用范围间隔。