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
相关产品推荐
相关产品推荐

