javascript - Mongo聚合管道更新或推送

标签 javascript node.js mongodb mongoose pipeline

我有一个 MongoDB 模型,其中包含作为对象的成员数组。

const guestSchema = new mongoose.Schema({
  salutation: {
    type: String,
  },
  members: [membersSchema],
  user: {
    type: mongoose.Schema.ObjectId,
    ref: 'User',
  },
});

成员架构:

const membersSchema = new mongoose.Schema({
  name: String,
  status: {
    type: String, 
    enum: ['regular', 'helper'],
    default: 'regular',
  },
});

我想实现在给定 ID 的文档存在的情况下进行更新,或者在数组中文档的 ID 不存在的情况下推送到数组。我使用聚合管道,但是我无法实现将新文档推送到数组。为什么我不能像这样使用push after else 语句。

const subDocumentToUpsert = { 'name': mem.name, 'status': mem.status, '_id': ObjectId(mem.id)}
      const subDocumentNoID = { 'name': mem.name, 'status': mem.status}


await Guest.findOneAndUpdate(
        { "_id": req.params.id },
        [
          {
            $set: {
              members: {
                $cond: {
                  if: { $in: [subDocumentToUpsert._id, '$members._id'] },
                  then: {
                    $map: {
                      input: '$members',
                      as: 'sub_document',
                      in: {
                        $cond: {
                          if: { $eq: ['$$sub_document._id', subDocumentToUpsert._id] },
                          then: subDocumentToUpsert,
                          else: '$$sub_document',
                        },
                      },
                    },
                  },
                  else: { 
                        $push: {
                          subDocumentNoID
                        }, 
                      },
                  },
                },
              },
            },
          },
      ]);

最好的方法是什么?谢谢

最佳答案

您可以执行以下操作:

db.collection.update({
 _id: {
  $in: [
    1,
    2
  ]
 }
},
[
{
$set: {
  members: {
    $cond: {
      if: {
        $in: [
          5,
          "$members._id"
        ]
      },
      then: {
        $map: {
          input: "$members",
          as: "sub",
          in: {
            $cond: {
              if: {
                $eq: [
                  "$$sub._id",
                  5
                ]
              },
              then: {
                _id: 5,
                status: "regular_updated",
                name: "Negan_updated"
              },
              else: "$$sub"
            },
            
          },
          
        },
        
      },
      else: {
        $concatArrays: [
          "$members",
          [
            {
              _id: 5,
              status: "regular_upserted",
              name: "Negan_upserted"
            }
          ]
        ]
      }    
    }  
  }
 }
}    
}
],
{
 multi: true
})

解释:

  1. 检查子对象中是否存在 _id:5,并通过 $map/$cond 仅更新具有 _id:5 的对象。

  2. 如果没有 _id:5,请使用 $concatArrays 将新对象添加到数组中。

Playground

关于javascript - Mongo聚合管道更新或推送,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74835363/

相关文章:

javascript - 单击带有 DOM 的按钮时卸载信息 - Javascript

javascript - 如何在地址栏中隐藏我的页面名称和扩展名?

mongodb - 如何计算匹配的数组元素

mongodb - Mongo-go-driver:超出上下文截止日期

mongodb - 在 scrapinghub spider 中添加设置

javascript - 如何在父窗口中打开iframe弹出窗口

javascript - 为什么 setTime 会增加一个小时?

node.js - CMake 错误 : Could NOT find SWIG (missing: SWIG_DIR)

node.js - 为什么 Node.js/Express 不接受来自本地主机的连接?

javascript - 通用 promise 重试逻辑