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

如何用Spring Data MongoDB实现含嵌套字段的Group聚合查询?

问题描述

需要将指定的MongoDB原生聚合查询转换为Spring Data MongoDB代码,要求返回结果的_id中包含嵌套的date对象(含年、月、日字段)。

集合数据结构

{
    date: ISODate("2022-12-11T01:13:00.000Z"),
    metadata: {
        homeId: '51b87ea3d846f450141ae58z',
        nodeId: '51b87ea3d846f450141ae58z'
    },
    value: 42,
    _id: ObjectId("63b583e30c1e523313b64ed5")
}

目标MongoDB原生查询

db.consumptions.aggregate([
    { $match : {"metadata.nodeId": "51b87ea3d846f450141ae58z"} },
    { $project: { 
        date: { 
            $dateToParts: { date: "$date"}
        }, 
        value: 1 
    } },
    { $group: { 
        _id: { 
            date: { 
                year: "$date.year", month: "$date.month", day: "$date.day"
            }
        }, 
        cumulValue: { $sum: "$value"} 
    } },
    { $sort : { "_id.date": -1} }
])

预期返回结果

[
    {
        _id: { 
            date: { year: 2022, month: 12, day: 11 } 
        },
        cumulValue: 42 
    }
]

尝试的Spring Data MongoDB代码(不符合预期)

MatchOperation matchOperation = Aggregation.match(
    new Criteria().andOperator(Criteria.where("metadata.nodeId").is(nodeId))
);
// projection Operation
ProjectionOperation projectionOperation = project("value")
    .and(DateOperators.dateOf("date").toParts()).as("date");
// group Operation
GroupOperation groupOperation = Aggregation.group(
    "date.year", "date.month", "date.day")
    .sum("value").as("cumulativeValue");
// Sort Operation
SortOperation sortOperation = sort(pageRequest.getSort());
Aggregation aggregation = Aggregation.newAggregation(
    matchOperation, projectionOperation, groupOperation, sortOperation);

当前不符合预期的结果

{
    _id: {
      year: 2022,
      month: 11,
      day: 11
    },
    cumulValue: 284
}
解决方案

要实现嵌套的date结构在_id中,需在GroupOperation里手动构建嵌套字段结构,而非直接传入字段路径。具体代码如下:

// Match操作保持不变
MatchOperation matchOperation = Aggregation.match(
    Criteria.where("metadata.nodeId").is(nodeId)
);

// Projection操作保持不变,生成包含year/month/day的date对象
ProjectionOperation projectionOperation = project("value")
    .and(DateOperators.dateOf("date").toParts()).as("date");

// 构建嵌套的_id结构:_id.date.year/month/day
GroupOperation groupOperation = Aggregation.group(
    Fields.from(
        Fields.field("date.year", "date.year"),
        Fields.field("date.month", "date.month"),
        Fields.field("date.day", "date.day")
    )
).sum("value").as("cumulValue");

// 按_id.date降序排序,与原生查询逻辑一致
SortOperation sortOperation = Sort.by(Sort.Direction.DESC, "_id.date");

// 组装聚合操作
Aggregation aggregation = Aggregation.newAggregation(
    matchOperation,
    projectionOperation,
    groupOperation,
    sortOperation
);

关键说明

  • 原代码中group("date.year", "date.month", "date.day")会将三个字段平放在_id下,而使用Fields.from()并指定嵌套字段路径(如date.year),可让MongoDB生成_id.date的嵌套结构。
  • 排序部分直接指定"_id.date"即可实现与原生查询一致的降序逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 16:05:25