Swift开发iOS日历:Firestore多字段不等过滤查询跨天日程方案求助
推荐最优方案:冗余存储覆盖时间维度字段
Firestore属于NoSQL数据库,通过适当冗余数据换查询性能是官方推荐的最佳实践,你可以通过新增两个冗余字段解决问题:
- 给
Event集合新增两个数组类型字段:coverDays:存储该日程覆盖的所有自然日,格式为yyyyMMdd的数字/字符串,比如2024年6月1日存为20240601coverMonths:存储该日程覆盖的所有自然月,格式为yyyyMM的数字/字符串,比如2024年6月存为202406
- 每次新增/修改日程时,自动根据
start和end时间戳计算上述两个字段的值写入文档,该计算量极小可忽略 - 查询整月日程时直接执行以下查询即可,该查询完全走索引,性能极高,只会返回当月关联的所有日程(含跨天、跨月日程):
// targetMonth为要查询的年月,比如2024年6月即202406 db.collection("Event") .whereField("user", isEqualTo: userID) .whereField("coverMonths", arrayContains: targetMonth) .getDocuments()
- 拿到查询结果后,本地遍历每个日程,判断其和当月每一天的时间重叠关系,分配到对应日期的日程列表即可。
无冗余字段替代方案(适合日程时长较短的场景)
如果你的业务中不存在超过3个月的超长日程,可采用范围裁剪查询降低数据拉取量:
- 先计算查询月份的开始时间戳
monthStart、结束时间戳monthEnd,以及monthStart往前推90天的时间戳preThreshold - 执行以下查询拉取候选数据:
db.collection("Event") .whereField("user", isEqualTo: userID) .whereField("start", isLessThanOrEqualTo: monthEnd) .whereField("start", isGreaterThanOrEqualTo: preThreshold) .getDocuments()
- 本地过滤出
end >= monthStart的日程,就是所有和当月重叠的有效日程。
该方案只会拉取最近3个月的相关数据,数据量可控,不会出现全量拉取历史数据的性能问题。
内容的提问来源于stack exchange,提问作者Vulps
相关产品推荐
相关产品推荐

