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

求Mongo聚合查询对应Java代码:车辆每日行驶距离去重求和

解决Mongo聚合查询转Java代码的问题

原生Mongo查询逻辑梳理

你的原生查询核心是三个聚合阶段:

  • $match:筛选指定vehicleId、2022-08-24当天(时间范围>2022-08-24T00:00:00且<2022-08-25T00:00:00)、distanceMiles>0的记录
  • $group:按vehicleId+distanceMiles组合分组,过滤重复的距离记录
  • $group:全局分组(_id: null),对去重后的distanceMiles求和,得到总行驶距离

对应原生查询的完整Java代码

用Spring Data MongoDB的Aggregation API实现如下:

// 构造UTC时区的日期范围,匹配原生查询的时间条件
LocalDate targetDate = LocalDate.of(2022, 8, 24);
Instant start = targetDate.atStartOfDay(ZoneOffset.UTC).toInstant();
Instant end = targetDate.plusDays(1).atStartOfDay(ZoneOffset.UTC).toInstant();

// 构建match条件
Criteria criteria = Criteria.where("vehicleId").is("ABCDEFGH")
        .and("timestamp").gt(start).lt(end)
        .and("distanceMiles").gt(0);

// 组装聚合管道
Aggregation aggregation = Aggregation.newAggregation(
        // 阶段1:匹配过滤
        Aggregation.match(criteria),
        // 阶段2:按vehicleId和distanceMiles分组去重
        Aggregation.group("vehicleId", "distanceMiles"),
        // 阶段3:全局分组求和,引用上一阶段_id中的distanceMiles
        Aggregation.group() // 不传参数等价于原生的_id: null
                .sum("_id.distanceMiles").as("totalDistance")
);

// 执行查询(需注入MongoTemplate实例)
AggregationResults<DistanceSumResult> results = mongoTemplate.aggregate(
        aggregation, "collection1", DistanceSumResult.class
);

// 结果接收实体类
class DistanceSumResult {
    private double totalDistance;
    // 生成getter、setter
}

适配你现有代码补全最后分组

你的代码额外做了日期格式化、取最新timestamp的操作,若要保留这些逻辑并补全求和分组,调整如下:

Criteria criteria = new Criteria();
criteria.andOperator(
        Criteria.where("timestamp").gte(start).lte(end),
        Criteria.where("vehicleId").in(vehicleIdList)
);

Aggregation aggregation = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.sort(Direction.DESC, "timestamp"),
        Aggregation.project("distanceMiles", "vehicleId", "timestamp")
                .and("timestamp").dateAsFormattedString("%Y-%m-%d").as("yearMonthDay"),
        // 你的现有分组逻辑:按车辆+日期分组,取最新记录并累计距离
        Aggregation.group("vehicleId", "yearMonthDay")
                .first("vehicleId").as("vehicleId")
                .first("timestamp").as("lastReported")
                .sum("distanceMiles").as("distanceMiles"),
        // 补全全局分组:对所有车辆每日的距离求和
        Aggregation.group()
                .sum("distanceMiles").as("totalDistance")
);

关键注意点

  • Spring Data MongoDB中,Aggregation.group()不传参数时,默认对应原生的_id: null全局分组
  • 引用上一阶段分组的复合_id字段时,直接用"_id.字段名"作为聚合函数的参数,比如sum("_id.distanceMiles")
  • 日期处理需保持时区一致,原生查询用UTC,Java代码也要对应使用ZoneOffset.UTC避免时间偏差

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 12:20:23