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

Spring Data Mongo中为数组运算符结果设别名实现对象合并

MongoDB聚合管道转Spring Data Mongo代码问题

我正在尝试将MongoDB聚合管道查询转换为Spring Data MongoDB代码。

目标MongoDB聚合管道

{ 
  $addFields: { 
    orders:{ 
      $map: {
          input: "$orders", 
          as: "order", 
          in: { 
              $mergeObjects: [ 
                "$$order", 
                { 
                  instance: { 
                    $first: { 
                        $filter: { 
                        input: "$instances", 
                        as: "instance", 
                        cond: { 
                          $eq: [ "$$order.instance.docKey", "$$instance._id" ]
                        }
                      }
                    }
                  }
                }
              ]
            }
        }
    }
 }
}

尝试的代码及问题

我编写了以下代码,但无法为ArrayOperators.first运算符返回的对象设置别名(即instance: { .... }):

AddFieldsOperation addInstanceFieldOp = 
Aggregation.addFields() 
.addFieldWithValue("orders", mapItemsOf("orders")
    .as("order") 
    .andApply(ObjectOperators.MergeObjects.mergeValuesOf("order") 
    .mergeWithValuesOf( ArrayOperators.First.first( filter("instances") .as("instance") 
    .by( ComparisonOperators.Eq.valueOf("order.instance.docKey") .equalTo("instance._id") )) ) )).build();

解决方案

要实现为$first结果设置instance别名的需求,需要将first的结果包装成包含instance键的对象,再与原order对象合并。修改后的代码如下:

方法一:使用Document包装

AddFieldsOperation addInstanceFieldOp = Aggregation.addFields()
    .addFieldWithValue("orders", mapItemsOf("orders")
        .as("order")
        .andApply(ObjectOperators.MergeObjects.mergeValuesOf("order")
            .mergeWith(new Document("instance", 
                ArrayOperators.First.first(
                    filter("instances")
                        .as("instance")
                        .by(ComparisonOperators.Eq.valueOf("order.instance.docKey")
                            .equalTo("instance._id"))
                )
            ))
        )
    ).build();

方法二:使用AggregationExpression构造

AddFieldsOperation addInstanceFieldOp = Aggregation.addFields()
    .addFieldWithValue("orders", mapItemsOf("orders")
        .as("order")
        .andApply(ObjectOperators.MergeObjects.mergeValuesOf("order")
            .mergeWith((AggregationExpression) ctx -> new Document("instance", 
                ArrayOperators.First.first(
                    filter("instances")
                        .as("instance")
                        .by(ComparisonOperators.Eq.valueOf(ctx.get("order") + ".instance.docKey")
                            .equalTo(ctx.get("instance") + "._id"))
                )
            ))
        )
    ).build();

核心逻辑:原代码直接将first的结果传入mergeWithValuesOf,但我们需要的是带instance键的对象结构,因此用Document将first表达式包装成{ instance: ... },再合并到原order对象中,这样就能匹配目标管道的结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 19:55:21