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

如何用Mongoose Schema存储HourTime参数,实现超市当前营业查询

基于Node.js/Express/Mongoose实现超市营业时间管理与实时营业查询

一、数据模型设计(Mongoose Schema)

先合理设计营业时间的存储结构,推荐按星期维度拆分,同时支持跨天营业(比如深夜关门的超市)。示例Schema如下:

const mongoose = require('mongoose');

const hourSchema = new mongoose.Schema({
  day: {
    type: Number,
    required: true,
    min: 0, // 0=周日,1=周一...6=周六
    max: 6
  },
  open: {
    type: String,
    required: true,
    match: /^([01]\d|2[0-3]):([0-5]\d)$/ // 验证24小时制格式,如"08:30"
  },
  close: {
    type: String,
    required: true,
    match: /^([01]\d|2[0-3]):([0-5]\d)$/
  }
});

const supermarketSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  hours: [hourSchema], // 存储一周7天的营业时间
  timezone: {
    type: String,
    default: 'Asia/Shanghai', // 可选:存储时区,处理跨区域时间问题
    required: true
  }
});

module.exports = mongoose.model('Supermarket', supermarketSchema);

设计要点:

  • 用数字0-6代表星期几,避免字符串歧义
  • 营业时间用24小时制字符串存储,格式验证确保合法性
  • 可选时区字段:如果超市分布在不同时区,必须存储时区信息,避免UTC时间偏差

二、实现"查询当前营业超市"的核心逻辑

核心是对比当前时间与超市的营业时间,重点处理跨天营业的场景(比如20:00开门,次日02:00关门)。

方法1:MongoDB聚合查询(推荐,数据库端处理更高效)

直接在数据库层面过滤,减少内存占用:

const Supermarket = require('./models/supermarket');

async function getOpenSupermarkets() {
  // 获取当前时间(以上海时区为例,若需多时区可引入时区转换库)
  const now = new Date();
  const currentDay = now.getDay(); // 0=周日
  const currentTime = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;

  return await Supermarket.aggregate([
    // 展开营业时间数组
    { $unwind: '$hours' },
    // 筛选当前星期的营业时间
    { $match: { 'hours.day': currentDay } },
    // 判断是否正在营业:分两种情况
    {
      $match: {
        $expr: {
          $or: [
            // 情况1:关门时间在当天(open <= 当前时间 <= close)
            { $and: [
              { $gte: [currentTime, '$hours.open'] },
              { $lte: [currentTime, '$hours.close'] }
            ]},
            // 情况2:跨天营业(当前时间 >= open 或者 当前时间 <= close)
            { $and: [
              { $gt: ['$hours.open', '$hours.close'] },
              { $or: [
                { $gte: [currentTime, '$hours.open'] },
                { $lte: [currentTime, '$hours.close'] }
              ]}
            ]}
          ]
        }
      }
    },
    // 合并回原文档结构(可选)
    { $group: {
      _id: '$_id',
      name: { $first: '$name' },
      currentHours: { $first: '$hours' },
      timezone: { $first: '$timezone' }
    }}
  ]);
}

方法2:内存中过滤(适合小数据集)

如果超市数量不多,可以先查询所有超市,再在Node.js层面过滤:

async function getOpenSupermarkets() {
  const allSupermarkets = await Supermarket.find();
  const now = new Date();
  const currentDay = now.getDay();
  const currentTime = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}`;

  return allSupermarkets.filter(market => {
    // 找到当前星期的营业时间
    const todayHours = market.hours.find(h => h.day === currentDay);
    if (!todayHours) return false; // 无当日营业时间,默认不营业

    const { open, close } = todayHours;
    // 处理跨天情况
    if (open > close) {
      return currentTime >= open || currentTime <= close;
    } else {
      return currentTime >= open && currentTime <= close;
    }
  });
}

三、Express接口开发

将查询逻辑封装为API接口:

const express = require('express');
const router = express.Router();
const getOpenSupermarkets = require('./services/supermarketService');

// 查询当前正在营业的超市
router.get('/open-now', async (req, res) => {
  try {
    const openMarkets = await getOpenSupermarkets();
    res.status(200).json({
      success: true,
      data: openMarkets
    });
  } catch (err) {
    res.status(500).json({
      success: false,
      message: '查询失败',
      error: err.message
    });
  }
});

module.exports = router;

四、最佳实践

  1. 时区处理优先:如果服务面向多区域用户,必须基于超市的时区计算当前时间,可使用moment-timezone或date-fns-tz库转换时间,避免用本地服务器时区。
  2. 缓存优化:营业状态不会实时频繁变化,可以缓存查询结果(比如用Redis),设置5-10分钟过期时间,减少数据库查询压力。
  3. 数据验证:创建/更新超市营业时间时,验证时间格式、星期范围,确保数据合法性,可使用Mongoose的validate钩子或Joi库。
  4. 支持特殊日期:如果需要处理节假日营业时间,可新增holidayHours字段,查询时优先检查是否有当日的节假日营业时间。
  5. 索引优化:为hours.day字段创建索引,提升查询效率:
    supermarketSchema.index({ 'hours.day': 1 });
    

内容的提问来源于stack exchange,提问作者Segev Solomon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 21:25:43