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

Spring MongoDB将字符串数组映射为对象数组的Java实现方法

Spring MongoDB将字符串数组转为带索引对象数组的实现方案

需求背景

现有MongoDB文档结构如下:

{
  "steps": ["step 1", "step 2"]
}

需要将查询结果中的steps字段从字符串数组,转换为包含name、index属性的对象数组,目标格式如下:

{
  "steps": [
    {"name": "step 1", "index": 1},
    {"name": "step 2", "index": 2}
  ]
}

已实现的原生MongoDB聚合逻辑

已经通过$reduce运算符实现了原生聚合投影语句:

{
  "$project": {
    "steps": {
      "$reduce": {
        "input": "$steps",
        "initialValue": [],
        "in": {"$concatArrays": [
          "$$value", 
          [{"name": "$$this", "index": {"$add": [1, {"$size": "$$value"}]}}]
        ]}
      }
    }
  }
}

问题点

将上述逻辑转换为Spring MongoDB的Java代码时,reduce的concat方法参数不知道如何构造包含name和index键的表达式,当前编写的代码片段如下:

var reduce = ArrayOperators.arrayOf("steps")
  .reduce(
    ArrayOperators.arrayOf("$$value").concat( ??? ))                               
  .startingWith(Collections.EMPTY_LIST);

解决方案

你可以通过AggregationExpression自定义内部对象的构造逻辑,完整代码如下:

import org.springframework.data.mongodb.core.aggregation.ArrayOperators;
import org.springframework.data.mongodb.core.aggregation.AggregationExpression;
import org.bson.Document;
import java.util.Collections;
import java.util.Arrays;

// 构造reduce逻辑
var reduce = ArrayOperators.arrayOf("steps")
    .reduce(
        ArrayOperators.arrayOf("$$value").concat(
            // 构造包含单个{name,index}对象的数组,作为concat的第二个参数
            AggregationExpression.from(ctx -> Arrays.asList(
                new Document("name", "$$this")
                    .append("index", new Document("$add", 
                        Arrays.asList(1, ArrayOperators.Size.lengthOfArray("$$value").toDocument(ctx))
                    ))
            ))
        )
    )
    .startingWith(Collections.EMPTY_LIST);

// 把reduce逻辑加入project阶段即可
var project = Aggregation.project().and(reduce).as("steps");

如果希望写法更贴近原生MongoDB语法,减少API记忆成本,也可以直接通过Document拼接整个reduce表达式:

AggregationExpression stepReduce = AggregationExpression.from(ctx -> 
    new Document("$reduce", 
        new Document("input", "$steps")
            .append("initialValue", Collections.emptyList())
            .append("in", new Document("$concatArrays", Arrays.asList(
                "$$value",
                Arrays.asList(new Document("name", "$$this")
                    .append("index", new Document("$add", Arrays.asList(1, new Document("$size", "$$value"))))
                )
            )))
    );

var project = Aggregation.project().and(stepReduce).as("steps");

两种写法最终生成的聚合语句和原生逻辑完全一致。

内容的提问来源于stack exchange,提问作者M. Prati

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.08 02:00:05