如果不存在则推送文档,如果存在于带有猫鼬的嵌套数组中,则更新

时间:2021-05-11 13:43:35

标签: javascript mongodb mongoose

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

   {
       user_id: '13',     
       stock: [
         {
           part_id: 'P456',
           quantity: 3
         },
         {
           part_id: 'P905',
           quantity: 8
         }
       ]
    }

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

1 个答案:

答案 0 :(得分:1)

<块引用>

我曾尝试使用 {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 });
  • 检查条件是否存在文档,然后将数量加一
  • 另外推送库存对象
// 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 } } }
  );
}

第二个选项:您可以update with aggregation pipeline从 MongoDB 4.2 开始,

  • $cond 检查 part_id 是否有货
    • 是的,$map 迭代 stock 的循环并检查条件,如果 part_id 匹配,则在 quantity 中添加 1,否则返回当前对象
    • 不,使用part_idstock中添加带有$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 }]] }
        ]
      }
    }
  }]
)

Playground