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

MongoDB:实现嵌套数组元素的新增或更新(索引去重)

问题分析与解决方案

先明确你原代码的几个核心问题:

  1. 字段名不匹配:MongoDB文档里用的是ItemID和ItemIndexes,但代码里写的是token_id、token_indexes,直接导致数组过滤器找不到对应元素,更新完全失效。
  2. 未覆盖新增Item场景:原代码只处理了ItemID已存在的情况,完全没考虑要新增Item的需求。
  3. 去重逻辑缺失:用$push而非$addToSet会导致ItemIndexes出现重复值;且你把二维数组直接传给$each,会把整个数组作为单个元素插入,而非展开添加单个索引。
  4. 无效语法:position: "$"是$push的无效参数,MongoDB不支持该选项。

正确实现方案(MongoDB 4.2+ 支持聚合管道更新)

用聚合管道可以在单次数据库操作里完成「更新已有Item索引+新增无Item」的需求,同时保证索引不重复:

public async appendItems(chestId: number, items: Array<{ ItemID: number; ItemIndexes: string[] }>) {
    await this.raw.updateOne(
        // 匹配目标Chest文档
        { ChestID: chestId },
        [
            {
                $set: {
                    Items: {
                        // 遍历传入的items数组,逐个处理
                        $reduce: {
                            input: items,
                            initialValue: "$Items", // 初始值为原Items数组
                            in: {
                                $let: {
                                    vars: {
                                        currentItem: "$$current", // 当前遍历的传入Item
                                        // 从原Items数组中查找是否存在相同ItemID的元素
                                        existingItem: {
                                            $first: {
                                                $filter: {
                                                    input: "$$value",
                                                    cond: { $eq: ["$$this.ItemID", "$$current.ItemID"] }
                                                }
                                            }
                                        }
                                    },
                                    in: {
                                        $cond: [
                                            // 情况1:ItemID已存在,更新ItemIndexes(自动去重)
                                            "$$existingItem",
                                            {
                                                $map: {
                                                    input: "$$value",
                                                    as: "item",
                                                    in: {
                                                        $cond: [
                                                            { $eq: ["$$item.ItemID", "$$currentItem.ItemID"] },
                                                            {
                                                                ItemID: "$$item.ItemID",
                                                                // 用$addToSet+ $each合并新旧索引,自动去重
                                                                ItemIndexes: { $addToSet: { $each: ["$$item.ItemIndexes", "$$currentItem.ItemIndexes"] } }
                                                            },
                                                            "$$item"
                                                        ]
                                                    }
                                                }
                                            },
                                            // 情况2:ItemID不存在,新增该Item到数组
                                            { $concatArrays: ["$$value", ["$$currentItem"]] }
                                        ]
                                    }
                                }
                            }
                        }
                    }
                }
            }
        ]
    );
}

代码说明

  1. $reduce遍历处理:遍历传入的每个Item,基于原Items数组逐步更新。
  2. $filter查找已有Item:每次遍历都检查原数组里是否有相同ItemID的元素。
  3. $addToSet保证去重:更新已有Item的索引时,用$addToSet配合$each,自动跳过已存在的索引值。
  4. $concatArrays新增Item:如果ItemID不存在,直接把当前Item追加到Items数组末尾。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:30:49