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

如何利用MongoDB内嵌数组的值批量更新文档

MongoDB数组匹配元素的批量更新问题

需求说明

需要批量更新MongoDB文档:找到所有results数组中存在id: "a1"且somethingElse: "aa"元素的文档,将文档的total字段加上该匹配元素的value值。

示例文档:

[
  {
    "_id": "Ox1",
    "results": [
      {"id": "a1", "somethingElse": "aa", "value": 1},
      {"id": "a2", "somethingElse": "bb", "value": 2},
      {"id": "a3", "somethingElse": "cc", "value": 3}
    ],
    "total": 0
  },
  {
    "_id": "Ox2",
    "results": [
      {"id": "a1", "somethingElse": "aa", "value": 44},
      {"id": "a4", "somethingElse": "bb", "value": 4},
      {"id": "a5", "somethingElse": "aa", "value": 5}
    ],
    "total": 0
  },
  {
    "_id": "Ox3",
    "results": [
      {"id": "a2", "somethingElse": "aa", "value": 1},
      {"id": "a3", "somethingElse": "aa", "value": 4},
      {"id": "a4", "somethingElse": "aa", "value": 5}
    ],
    "total": 0
  }
]

预期结果:

  • Ox1的total变为1
  • Ox2的total变为44
  • Ox3不满足条件,无更新

原代码问题

原filter部分逻辑正确,但普通更新操作符无法直接引用数组中匹配元素的value值,需要使用聚合管道更新(MongoDB 4.2及以上版本支持)。

解决方案

使用聚合管道作为UpdateMany的更新参数,通过聚合操作筛选出目标元素的value值,再计算新的total。

完整Go代码如下:

import (
	"context"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
)

func updateTotal(collection *mongo.Collection) error {
	// 过滤条件:匹配results数组中存在id=a1且somethingElse=aa的文档
	filter := bson.D{
		{Key: "results", Value: bson.D{
			{Key: "$elemMatch", Value: bson.D{
				{Key: "id", Value: "a1"},
				{Key: "somethingElse", Value: "aa"},
			}},
		}},
	}

	// 聚合管道更新:计算新的total值
	update := bson.D{
		{Key: "$set", Value: bson.D{
			{Key: "total", Value: bson.D{
				{Key: "$sum", Value: bson.A{
					"$total",
					// 先筛选出匹配的数组元素,再取第一个的value
					bson.D{
						{Key: "$let", Value: bson.D{
							{Key: "vars", Value: bson.D{
								{Key: "matched", Value: bson.D{
									{Key: "$arrayElemAt", Value: bson.A{
										bson.D{
											{Key: "$filter", Value: bson.D{
												{Key: "input", Value: "$results"},
												{Key: "cond", Value: bson.D{
													{Key: "$and", Value: bson.A{
														bson.D{{Key: "$eq", Value: bson.A{"$$this.id", "a1"}}},
														bson.D{{Key: "$eq", Value: bson.A{"$$this.somethingElse", "aa"}}},
													}},
												}},
											}},
										},
										0,
									}},
								}},
							}},
							{Key: "in", Value: "$$matched.value"},
						}},
					},
				}},
			}},
		}},
	}

	// 执行批量更新
	_, err := collection.UpdateMany(context.TODO(), filter, update)
	return err
}

代码说明

  1. $filter:遍历results数组,筛选出满足id="a1"且somethingElse="aa"的元素,返回匹配元素数组。
  2. $arrayElemAt:取筛选后数组的第一个元素(filter已确保至少有一个匹配)。
  3. $let:将匹配元素赋值给临时变量,方便提取其value字段。
  4. $sum:将原total值与匹配元素的value相加,得到新的total值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 20:23:38