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

医院无预约日期如何存入MongoDB?附聚合查询代码

如何在MongoDB中补存无预约的日期记录

针对你的问题——数据库中仅存储了有预约的日期(7.24、7.25),无预约的7.26未存入,这里提供两种可行方案:

方案一:主动插入缺失日期的空记录

如果需要永久保存无预约日期的记录,按以下步骤操作:

  1. 生成目标日期范围的所有日期
    用Java代码遍历生成指定时间范围内的所有日期(比如最近30天):
    List<LocalDate> dateRange = new ArrayList<>();
    LocalDate endDate = LocalDate.now();
    LocalDate startDate = endDate.minusDays(30);
    for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
        dateRange.add(date);
    }
    
  2. 查询数据库中已存在的日期
    从目标集合中提取当前医院已有的预约日期:
    Query query = new Query();
    query.addCriteria(hospCriteria);
    query.addCriteria(dateCriteria);
    query.fields().include("AppointmentDate");
    List<Document> existingDates = mongoTemplate.find(query, Document.class, "your_collection_name");
    Set<LocalDate> existingDateSet = existingDates.stream()
        .map(doc -> doc.getDate("AppointmentDate").toInstant().atZone(ZoneId.systemDefault()).toLocalDate())
        .collect(Collectors.toSet());
    
  3. 插入缺失日期的空记录
    遍历日期列表,将不在现有集合中的日期插入数据库,字段需匹配集合结构:
    for (LocalDate date : dateRange) {
        if (!existingDateSet.contains(date)) {
            Document emptyApp = new Document();
            emptyApp.put("Hospital_clinic", Collections.singletonMap("id", hospitalId));
            emptyApp.put("AppointmentDate", Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()));
            emptyApp.put("AppointmentType", "IPD");
            emptyApp.put("appointmentStatus", "Active"); // 可根据业务调整为"Empty"标识空记录
            mongoTemplate.insert(emptyApp, "your_collection_name");
        }
    }
    

方案二:通过聚合管道补全缺失日期(查询时生成,可选存入)

如果不需要永久存储空记录,仅需查询结果包含所有日期,可修改聚合管道生成连续日期并左连接现有数据,自动补0:
修改你的聚合代码,加入日期生成和左连接逻辑:

// 生成连续日期序列的自定义聚合阶段
AggregationOperation generateDateRange = context -> {
    Date start = (Date) dateCriteria.getCriteriaObject().get("AppointmentDate").get("$gte");
    Date end = (Date) dateCriteria.getCriteriaObject().get("AppointmentDate").get("$lte");
    long dayMs = 24 * 60 * 60 * 1000;
    long daysDiff = (end.getTime() - start.getTime()) / dayMs + 1;

    return new Document("$addFields",
        new Document("dates",
            new Document("$map",
                new Document("input", new Document("$range", Arrays.asList(0, daysDiff)))
                    .append("as", "offset")
                    .append("in", new Document("$dateAdd",
                        new Document("startDate", start)
                            .append("unit", "day")
                            .append("amount", "$$offset")
                    ))
            )
        )
    );
};

// 拆分日期序列为单独文档
AggregationOperation unwindDates = Aggregation.unwind("dates");

// 左连接现有预约统计数据
AggregationOperation lookupAppointments = Aggregation.lookup(
    "your_collection_name",
    "dates", "AppointmentDate",
    "appointmentStats"
);

// 处理左连接结果,空记录补0
AggregationOperation projectWithFill = Aggregation.project()
    .and("dates").as("AppointmentDate")
    .and(new Document("$ifNull", Arrays.asList(new Document("$arrayElemAt", Arrays.asList("appointmentStats.ipdCount", 0)), 0))).as("ipdCount");

// 构建完整聚合管道
Aggregation aggregation = newAggregation(
    // 生成包含日期范围的基础文档
    Aggregation.match(Criteria.where("_id").exists(false)),
    generateDateRange,
    unwindDates,
    lookupAppointments,
    projectWithFill,
    // 过滤目标医院和有效IPD预约
    Aggregation.match(hospCriteria),
    Aggregation.match(ipdCriteria)
);

// 执行聚合获取完整结果
List<Document> fullResults = mongoTemplate.aggregate(aggregation, "your_collection_name", Document.class).getMappedResults();

// 若需要将结果存入数据库,直接遍历保存
for (Document result : fullResults) {
    mongoTemplate.save(result, "your_collection_name");
}

两种方案对比

  • 方案一:永久存储空记录,后续查询更高效,但会增加数据库存储量。
  • 方案二:仅在查询时生成完整日期序列,节省存储,但每次查询需要额外的日期生成逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 15:15:28