You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多城市礼拜时间存储场景MongoDB Schema设计合理性咨询

现有Schema设计的问题

你当前的设计不符合MongoDB最佳实践,核心问题如下:

  • 单文档体积极易超过MongoDB 16MB的上限:按34个省份、平均每个省15个地级市、10年共3652天计算,单个省份文档的嵌套数据量会轻松突破16MB限制,最终会导致写入失败。
  • 查询效率极低:如果仅需要获取单个城市某一天的礼拜时间,你需要加载整个省份的全量数据,再遍历多层嵌套结构才能拿到目标数据,没有办法做高效的查询优化。
  • 维护成本极高:修改单日某个时间字段需要写多层嵌套的更新路径,极易出错,同时高并发场景下对同一个大文档的频繁更新会触发大量写冲突。
  • 索引适配困难:多层嵌套的结构下无法针对高频查询场景创建高效的复合索引,数据量上来后查询延迟会非常高。
适配该场景的最佳实践方案

我们根据高频查询场景(通常是查「某城市某段时间的礼拜时间」),采用分集合、细粒度存储的设计,一共拆为2个集合:

1. 地域基础信息集合 geo_locations

存储省份、城市的静态基础信息,避免数据冗余,单条文档对应单个城市:

{
  _id: ObjectId("xxx"),
  province_name: "Province A",
  province_slug: "province-a",
  city_name: "City A",
  city_slug: "city-a",
  latitude: "4° 09' 31.76\" N",
  longitude: "96° 07' 28.86\" E" // 注意你原字段名拼写错误longtitude建议改为longitude
}

可以给 province_slug、city_slug 建唯一索引,方便快速关联查询。

2. 礼拜时间集合 prayer_times

如果你的高频查询是按天取数据,采用单条文档对应单个城市单日的礼拜时间,结构如下:

{
  _id: ObjectId("xxx"),
  city_slug: "city-a",
  year: 2021,
  month: 1,
  day: 1,
  date_str: "Friday, 01/01/2021",
  imsak: "05:11",
  subuh: "05:21",
  terbit: "06:39",
  dhuha: "07:08",
  dzuhur: "12:42",
  ashar: "16:05",
  maghrib: "18:39",
  isya: "19:53"
}

如果高频查询是按月取整月数据,也可以调整为单条对应单个城市单月的时间,进一步减少文档数量:

{
  _id: ObjectId("xxx"),
  city_slug: "city-a",
  year: 2021,
  month: 1,
  days: {
    "1": { /* 单日时间字段 */ },
    "2": { /* 单日时间字段 */ },
    // 当月其他日期
  }
}
优化后方案的优势
  • 单文档体积远小于16MB上限,完全不会触发文档大小限制。
  • 查询效率极高:给prayer_times集合创建复合索引 { city_slug: 1, year: 1, month: 1, day: 1 } 后,任意城市单日/单月/单年的时间查询都可以走索引覆盖,响应速度可控制在毫秒级。
  • 更新成本极低:修改某一天的时间只需要过滤对应city_slug和日期即可,路径简单,并发更新冲突概率极低。
  • 扩展性强:后续需要新增年份数据只需要直接写入prayer_times集合,不需要修改原有文档结构。

内容的提问来源于stack exchange,提问作者R.M. Reza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 12:24:04