【问题标题】:How to upsert with MongoDB array?如何使用 MongoDB 数组进行更新插入?
【发布时间】:2021-07-02 13:13:00
【问题描述】:

我正在尝试在 MongoDB 数组中插入、更新值。
我的 MongoDB 版本是 4.0.5。

这是我的收藏:

{
    'id': 1,
    'array': [{
        'code': 'a'
    }, {
        'code': 'b'
    }]
}

我正在尝试进行一些 upsert 查询以插入/更新到数组中,但直到那时我才找到一个好的解决方案。

我的过滤器是:

  • 'id'(指向正确的文档)
  • 'array.code'(指向正确的数组单元)
  1. 如果文档存在于集合中但没有'code': 'c'的单元格
db.test.update({
        'id': 1
    }, {
        $set: {'array.$[elem].test':'ok'}
    }, {
        upsert: true,
        arrayFilters: [{'elem.code': 'c'}]
    }
)

我没有错误,但也没有更新。
我想像这样在数组中插入元素:

// Desired result
{
    'id': 1,
    'array': [{
        'code': 'a'
    }, {
        'code': 'b'
    }, {
        'code': 'c'
        'test': 'ok'
    }]
}
  1. 如果文档在集合中不存在
db.test.update({
        'id': 3
    }, {
        $set: {'array.$[elem].test':'ok'}
    }, {
        upsert: true,
        arrayFilters: [{'elem.code': 'a'}]
    }
)

在这种情况下,我有这个错误:

WriteError: The path 'array' must exist in the document in order to apply array updates., full error: {'index': 0, 'code': 2, 'errmsg': "The path 'array' must exist in the document in order to apply array updates."}

我想用这样的查询元素更新一个新文档:

// Desired result
{
    'id': 3,
    'array': [{
        'code': 'a'
        'test': 'ok'
    }]
}

查询参数中的upsert: true 似乎不适用于数组。
我们将非常感谢您的帮助。

【问题讨论】:

  • upsert: true 适用于文档,即如果不存在,则插入新的 文档。它不适用于数组中的元素。

标签: arrays mongodb mongodb-query


【解决方案1】:

upsert 在数组中无效,如果你确实将 MongoDB 版本从 4.0.5 更新到 4.2,那么你可以从 MongoDB 4.2 开始使用update with aggregation pipeline

案例1:如果文档存在于集合中但没有'code': 'c'的单元格:

var id = 2;
var item = { code: "c", test: "ok" };

Playground

案例2:如果文档不存在于集合中:

var id = 3;
var item = { code: "a", test: "ok" };

Playground

  • $ifNull 检查该字段是否不存在然后返回空
  • $cond 检查输入 code 是否在数组中
    • 是的,然后$mep 迭代array 的循环并检查条件是否匹配然后更新其他字段,否则返回一个空对象
    • $mergeObjects 将当前对象与更新的字段合并
    • 不,$concatArrays 将当前 array 与新项目对象连接
db.collection.update(
  { "id": id },
  [{
    $set: {
      array: {
        $cond: [
          {
            $in: [item.code, { $ifNull: ["$array.code", []] }]
          },
          {
            $map: {
              input: "$array",
              in: {
                $mergeObjects: [
                  "$$this",
                  {
                    $cond: [{ $eq: ["$$this.code", "c"] }, item, {}]
                  }
                ]
              }
            }
          },
          {
            $concatArrays: [{ $ifNull: ["$array", []] }, [item]]
          }
        ]
      }
    }
  }],
  { upsert: true }
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-23
    • 2016-10-08
    • 2017-07-12
    • 2012-09-10
    • 1970-01-01
    • 2015-11-08
    • 2021-07-21
    • 2023-01-06
    相关资源
    最近更新 更多