【问题标题】:MongoDB conditionial updateMongoDB 条件更新
【发布时间】:2022-02-22 22:22:07
【问题描述】:

我在这里绕了一圈,希望能得到一些帮助。我要做的是更新或创建包含在数组中的嵌套对象,具体取决于该对象是否存在。

我有一个用户集合,一个用户文档具有以下结构:

{
  schema_version: 1,
  display_name: 'xxxxxx',
  email: 'xxxxxx',
  email_verified:'xxxxxx',
 ...
  custom_data: {

    stripe_id: 'xxx',
    subscriptions: [{
   subscription_id: xxxx,
    ....

     }],
 ...

  },
}

在来自 Stripe 的 webhook 调用中,我得到一个带有 subscription_idstripe_id 的订阅对象。 我要做的是检查subscription_id 是否存在,如果存在,则更新文档,如果不存在,则在订阅数组中创建文档stripe_id 匹配的用户文档

如果我按照以下方式做某事:

db.collection.update(
 {subscription_id: subscription.id},
 { $set: { 'custom_data.subscriptions': subscriptionData } },
 { upsert: true }
)

问题是我创建的订阅对象未绑定到我的用户文档,其中 stripeID 匹配。

另一方面,如果我这样做:

db.collection.update(
 {'custom_data.stripe_id': stripe_id},
 { $set: { 'custom_data.subscriptions': subscriptionData } },
 { upsert: true }
)

我最终可能会在订阅数组中创建重复对象,而事实上我想更新订阅 ID 匹配的现有对象。

有什么方法可以在 Mongo 的一个查询中做到这一点,还是我必须在 if 语句中使用 2 个查询?

提前感谢您对此的任何澄清。

【问题讨论】:

  • 您可以更新数组元素以防它存在,否则插入一个新元素 - 您可以在单个更新操作中完成。请参阅使用聚合管道进行更新的主题。也搜索类似的帖子。

标签: mongodb mongodb-query


【解决方案1】:

您可以使用聚合管道执行以下操作:

  1. $match$or 条件来搜索 custom_data.subscriptions.subscription_idcustom_data.stripe_id
  2. $addFields$map 在匹配时有条件地更新您的订阅对象
  3. $addFields$setUnion 为插入案例插入传入订阅对象的条目
  4. $merge更新回原来的集合
db.collection.aggregate([
  {
    $match: {
      $expr: {
        $or: [
          {
            $eq: [
              "$custom_data.subscriptions.subscription_id",
              "xxxx"
            ]
          },
          {
            $eq: [
              "$custom_data.stripe_id",
              "xxx"
            ]
          }
        ]
      }
    }
  },
  {
    "$addFields": {
      "custom_data": {
        subscriptions: {
          "$map": {
            "input": "$custom_data.subscriptions",
            "as": "s",
            "in": {
              "$cond": {
                // if subscription_id matched, replace with your incoming object
                "if": {
                  $eq: [
                    "$$s.subscription_id",
                    "xxxx"
                  ]
                },
                "then": {
                  subscription_id: "incoming_sub_id"
                },
                // if not matched, keep the original object
                "else": "$$s"
              }
            }
          }
        }
      }
    }
  },
  {
    "$addFields": {
      "custom_data": {
        subscriptions: {
          // insert case; if the subscription array is empty, then union with your incoming object
          $setUnion: [
            "$custom_data.subscriptions",
            [
              {
                subscription_id: "incoming_sub_id"
              }
            ]
          ]
        }
      }
    }
  },
  {
    "$merge": {
      "into": "collection",
      "on": "_id",
      "whenMatched": "replace"
    }
  }
])

这是Mongo playground 供您参考。

【讨论】:

    猜你喜欢
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 2013-10-16
    • 1970-01-01
    • 2017-10-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多