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

MongoDB条件更新:仅最后价格不同时推送数组数据(支持Upsert)

MongoDB 数组更新问题解决

问题背景

现有MongoDB文档结构如下:

{
    "accountName": "pippo",
    "whishList": {
        "element1": [
            { "price": 25, "time": "2024-02-20T20:00:00.000+00:00" },
            { "price": 30, "time": "2024-02-21T20:00:00.000+00:00" }
        ]
    }
}

需要实现一个函数满足以下需求:

  • 接收price参数,仅当whishList.element1数组最后一个元素的price与传入值不同时,才向数组推送包含该price和当前时间的对象
  • 若集合中不存在对应accountName的文档,则自动创建(启用upsert: true)

原尝试代码无法正常运行:

async function updatePrice(id, element, price) {
    const filter = { 
        accountName: id,
        $expr: { $ne: [ {$last : `whishList.${element}`}.price , price ] }
    }
    const update = {     
        $push: {
            `whishList.${element}`: {
                value: valore,
                time: new Date()
            }
        }
    };

    await prova.updateOne(filter, update, { upsert: true });
}

原代码问题分析

  1. $expr语法错误:{$last : \whishList.${element}`}.price写法不符合MongoDB表达式规则,无法正确获取数组最后一个元素的price`字段
  2. 字段名与变量错误:更新时误用了value: valore,需求是price字段,且valore为未定义变量
  3. Upsert逻辑冲突:原过滤条件会导致文档不存在时,$expr的判断无法触发upsert,需要调整逻辑覆盖空文档场景

修正后的代码

async function updatePrice(id, element, price) {
    const arrayPath = `whishList.${element}`;
    const filter = {
        accountName: id,
        $or: [
            // 文档存在,数组最后一个元素price与传入值不同
            {
                $expr: {
                    $ne: [
                        { $getField: { field: "price", input: { $last: `$${arrayPath}` } } },
                        price
                    ]
                }
            },
            // 文档存在,但目标数组为空
            { [arrayPath]: { $size: 0 } },
            // 文档不存在,用于触发upsert
            { accountName: { $exists: false } }
        ]
    };

    const update = {
        $setOnInsert: {
            // Upsert时初始化文档结构
            whishList: { [element]: [] }
        },
        $push: {
            [arrayPath]: {
                price: price,
                time: new Date()
            }
        }
    };

    await prova.updateOne(filter, update, { upsert: true });
}

代码说明

  • 多场景过滤:通过$or覆盖三种需要更新/插入的情况,确保所有符合条件的场景都能命中
  • 正确获取数组元素:用$last结合$getField,准确提取数组最后一个元素的price字段进行比较
  • 安全初始化:$setOnInsert仅在创建新文档时初始化whishList结构,避免覆盖现有数据
  • 字段修正:将错误的value改为需求的price字段,使用传入的price参数

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 14:22:19