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

MongoDB聚合框架Java实现:按两数组值拼接分组计算

解决方案:用Java Aggregation Framework实现数组元素配对拼接分组

要实现将document1和document2对应位置的value拼接成「doc1A (doc2A)」格式作为分组键,核心思路是先将两个数组拉链配对,再展开拼接,最后分组计算。以下是具体实现步骤和代码示例:

前提说明

首先需要修正你提供的文档结构:MongoDB数组中不能混合对象和独立键值对(比如"metric1":0.0直接放在document2数组里是非法的)。假设修正后的合法结构如下(metric1/metric2属于document2的每个元素,或作为文档顶级字段):

{
  "_id": ObjectId("59ce3bb32708c95ee2168e2f"),
  "document1": [{"value": "doc1A"}, {"value": "doc1B"}, {"value": "doc1C"}, {"value": "doc1D"}, {"value": "doc1E"}, {"value": "doc1F"}],
  "document2": [
    {"value": "doc2A", "metric1": 1.0, "metric2": 2.0},
    {"value": "doc2B", "metric1": 3.0, "metric2": 4.0},
    {"value": "doc2C", "metric1": 5.0, "metric2": 6.0},
    {"value": "doc2D", "metric1": 7.0, "metric2": 8.0}
  ]
}

实现步骤(Spring Data MongoDB版本)

1. 导入依赖类

import org.springframework.data.mongodb.core.aggregation.*;

2. 构建聚合管道

// 步骤1:将document1和document2数组拉链配对,得到[[doc1元素, doc2元素]]格式的数组
ProjectionOperation zipArrays = Aggregation.project()
    .and(ZipOperators.zip()
        .withInputs("document1", "document2")
        .useDefaults()) // 数组长度不同时用默认值填充,可选
    .as("pairedDocs");

// 步骤2:展开配对后的数组,每个文档对应一对元素
UnwindOperation unwindPairs = Aggregation.unwind("pairedDocs");

// 步骤3:拼接分组键,并提取需要计算的metric字段
ProjectionOperation projectGroupKey = Aggregation.project()
    .and(StringOperators.Concat.valueOf("pairedDocs.0.value")
        .concat(" (")
        .concat("pairedDocs.1.value")
        .concat(")"))
    .as("groupKey")
    .and("pairedDocs.1.metric1").as("metric1")
    .and("pairedDocs.1.metric2").as("metric2");

// 步骤4:按拼接后的字符串分组,执行聚合计算(示例为sum和avg,可按需替换)
GroupOperation groupByKey = Aggregation.group("groupKey")
    .sum("metric1").as("totalMetric1")
    .avg("metric2").as("averageMetric2");

// 步骤5:可选,美化输出结果,将_id重命名为groupKey
ProjectionOperation finalProjection = Aggregation.project("totalMetric1", "averageMetric2")
    .and("_id").as("groupKey");

// 组装完整聚合管道
Aggregation aggregation = Aggregation.newAggregation(
    zipArrays,
    unwindPairs,
    projectGroupKey,
    groupByKey,
    finalProjection
);

// 执行聚合(替换为你的集合名和结果实体类)
AggregationResults<YourResultPOJO> results = mongoTemplate.aggregate(
    aggregation,
    "your_collection_name",
    YourResultPOJO.class
);

实现步骤(原生MongoDB Java驱动版本)

如果使用原生驱动,代码逻辑类似:

import com.mongodb.client.model.*;
import org.bson.conversions.Bson;
import java.util.Arrays;

List<Bson> pipeline = Arrays.asList(
    Aggregates.project(
        Projections.computed("pairedDocs",
            ZipOperators.zip(Arrays.asList("$document1", "$document2"))
        )
    ),
    Aggregates.unwind("$pairedDocs"),
    Aggregates.project(
        Projections.fields(
            Projections.computed("groupKey",
                StringOperators.concat("$pairedDocs.0.value", " (", "$pairedDocs.1.value", ")")
            ),
            Projections.include("pairedDocs.1.metric1", "pairedDocs.1.metric2")
        )
    ),
    Aggregates.group("$groupKey",
        Accumulators.sum("totalMetric1", "$pairedDocs.1.metric1"),
        Accumulators.avg("averageMetric2", "$pairedDocs.1.metric2")
    ),
    Aggregates.project(
        Projections.fields(
            Projections.excludeId(),
            Projections.computed("groupKey", "$_id"),
            Projections.include("totalMetric1", "averageMetric2")
        )
    )
);

// 执行聚合
MongoCollection<Document> collection = mongoClient.getDatabase("your_db").getCollection("your_collection");
for (Document doc : collection.aggregate(pipeline)) {
    System.out.println(doc.toJson());
}

关键细节说明

  • $zip操作:将两个数组的对应元素配对,确保每个document1元素和同位置的document2元素绑定在一起。如果数组长度不一致,可通过useDefaults()或defaults()参数填充缺失值,避免数据丢失。
  • 拼接字符串:使用$concat操作符将两个value字段和固定字符拼接成目标格式,若存在value字段缺失的情况,可搭配$ifNull处理(比如$ifNull("$pairedDocs.0.value", "N/A"))。
  • 分组计算:以拼接后的groupKey作为分组ID,根据业务需求选择合适的累加器(sum、avg、count等)。

内容的提问来源于stack exchange,提问作者Dr. Mza

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:58:12