如果文档不存在则推送文档,如果存在于嵌套数组中则使用 mongoose 更新

TKX*_*TKX 1 javascript mongoose mongodb

我有 mongo 文档,当出现新订单时,如果订单part_id已经存在,我需要推送它或更新(增加数量)。

   {
       user_id: '13',     
       stock: [
         {
           part_id: 'P456',
           quantity: 3
         },
         {
           part_id: 'P905',
           quantity: 8
         }
       ]
    }
Run Code Online (Sandbox Code Playgroud)

我尝试过使用{upsert: true}$inc找不到解决方案。

tur*_*hal 6

我尝试使用 {upsert: true} 和 $inc 但找不到解决方案

upsert 不支持对象数组,您可以尝试 2 个查询,第一个查找,第二个更新,

使用以下方法计算文档数量countDocuments

let user_id = "13";
let part_id = "P456";
let hasDoc = await YourSchema.countDocuments({ user_id: user_id, "stock.part_id": part_id });
Run Code Online (Sandbox Code Playgroud)
  • 检查文档是否存在,然后将数量加一
  • 否则推送库存对象
// Document already exists, so increment it value
if (hasDoc > 0) {
  await YourSchema.updateOne(
    { user_id: user_id, "stock.part_id": part_id },
    { $inc: { "stock.$.quantity": 1 } }
  );
} 

// Document not exists then add document
else {
  await YourSchema.updateOne(
    { user_id: user_id },
    { $push: { stock: { part_id: part_id, quantity: 1 } } }
  );
}
Run Code Online (Sandbox Code Playgroud)

第二个选项:您可以从 MongoDB 4.2 开始使用聚合管道进行更新,

  • $cond检查是否part_id有库存
    • 是的,$map迭代循环stock并检查条件是否part_id匹配,然后添加 1,quantity否则返回当前对象
    • 否,添加新对象并使用part_id数量stock$concatArrays
let user_id = "13";
let part_id = "P456";
db.collection.update(
  { user_id: user_id },
  [{
    $set: {
      stock: {
        $cond: [
          { $in: [part_id, "$stock.part_id"] },
          {
            $map: {
              input: "$stock",
              in: {
                $cond: [
                  { $eq: ["$$this.part_id", part_id] },
                  {
                    part_id: "$$this.part_id",
                    quantity: { $add: ["$$this.quantity", 1] }
                  },
                  "$$this"
                ]
              }
            }
          },
          { $concatArrays: ["$stock", [{ part_id: part_id, quantity: 1 }]] }
        ]
      }
    }
  }]
)
Run Code Online (Sandbox Code Playgroud)

操场