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

如何精简MongoDB查询实现数组元素存在则更新count不存在则插入

MongoDB单语句实现数组元素更新/插入原子操作

需求说明

  • 匹配from、to字段的目标文档
  • 若文档内json数组已存在对应asset_id的元素,将该元素的count值加1
  • 若数组内不存在对应asset_id的元素,向数组插入格式为{asset_id: 目标id, count: 1}的新元素
  • 支持主文档不存在时自动创建(upsert)

目标文档结构如下:

{
  from: '1', 
  to: '2', 
  json:[
    {asset_id: id, count: 1},
    {asset_id: id, count: 1},
    {asset_id: id, count: 1}
  ]
}

原有方案问题

当前拆分3条updateOne执行的写法存在冗余,且并发场景下会出现竞态问题,比如两条请求同时判断到元素不存在,会重复插入元素。使用MongoDB 4.2+版本支持的聚合管道更新能力,可以单条原子语句实现全部逻辑。

单语句实现代码

db.你的集合名.updateOne(
  // 主文档匹配条件
  {
    from: res[i].from,
    to: res[i].to
  },
  [
    // 第一阶段:初始化字段,兼容upsert新建文档的场景
    {
      $set: {
        from: res[i].from,
        to: res[i].to,
        json: { $ifNull: ["$json", []] }
      }
    },
    // 第二阶段:判断数组元素是否存在,分别处理计数+1/追加新元素逻辑
    {
      $set: {
        json: {
          $cond: [
            // 判断条件:数组内是否已存在对应asset_id
            {
              $anyElementTrue: {
                $map: {
                  input: "$json",
                  as: "item",
                  in: { $eq: ["$$item.asset_id", res[i].asset_id] }
                }
              }
            },
            // 存在则遍历数组,匹配项count+1
            {
              $map: {
                input: "$json",
                as: "item",
                in: {
                  $cond: [
                    { $eq: ["$$item.asset_id", res[i].asset_id] },
                    { $mergeObjects: ["$$item", { count: { $add: ["$$item.count", 1] } }] },
                    "$$item"
                  ]
                }
              }
            },
            // 不存在则拼接新元素到数组末尾
            {
              $concatArrays: ["$json", [{ asset_id: res[i].asset_id, count: 1 }]]
            }
          ]
        }
      }
    }
  ],
  // 开启upsert,主文档不存在时自动创建
  { upsert: true }
)

注意事项

  • 该写法依赖MongoDB 4.2及以上版本的聚合管道更新能力,目前主流线上MongoDB实例均支持该版本
  • 整个更新过程是原子执行的,不会出现拆分多条语句时的并发写入冲突问题,无需额外加事务
  • 如果使用的MongoDB版本低于4.2,没有原生单语句实现该需求的方案,必须分两次查询判断后再更新,建议升级实例版本

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:57:16