【问题标题】:Mongoose: if object is present, increment value, if not push into arrayMongoose:如果对象存在,则增加值,如果不推入数组
【发布时间】:2017-08-03 10:06:01
【问题描述】:

伙计们,我有以下型号:

articles: [
    {
      _id: {
        type: ObjectId,
        ref: "Article"
      },
      amount: {
        type: Number
      }
    }
  ]

这个想法是查找数组中是否存在文章,如果存在,则增加数量,否则将值推入数组。

目前,我正在使用以下代码,但我确信有一种方法可以只使用一个 findandupdate

function(warehouse, article, amount) {
Warehouse.findOne({
  _id: warehouse,
  "articles._id": article
})
  .then(function(found) {
    if (found) {
      return Warehouse.findOneAndUpdate(
        {
          _id: warehouse,
          "articles._id": article
        },
        {
          $inc: { "articles.$.amount": amount }
        }
      );
    }
    return Warehouse.findOneAndUpdate(
      {
        _id: warehouse
      },
      {
        $push: {
          articles: {
            _id: article,
            amount: amount,
            serialized: false
          }
        }
      }
    );
  })

编辑:

我正在使用 Neil 建议,因为我不需要从此查询返回的文档。

所以这里是bulkwrite:

 Warehouse.bulkWrite(
  [
    {
      updateOne: {
        filter: { _id: warehouse, "articles._id": article },
        update: {
          $inc: {
            "articles.$.amount": amount
          }
        }
      }
    },
    {
      updateOne: {
        filter: { _id: warehouse },
        update: {
          $addToSet: {
            articles: {
              _id: article,
              amount: amount,
              serialized: true
            }
          }
        }
      }
    }
  ],

不知何故,第二次更新总是被执行,即使它是一个 $addToSet。关于如何避免这种行为的任何想法?

【问题讨论】:

  • 不适用于.findOneAndUpdate(),因为该特定方法旨在“返回”更新的文档。您可以使用.bulkWrite() 在“一次调用”中执行此操作,但当然该方法的本质是它不返回文档。你应该问“我真的需要返回文件吗?” 然后当然应该是“我可以接受.findOne() 之后 .bulkWrite() 完成了吗?”。这应该决定你需要做什么。
  • @NeilLunn 我不需要返回文档。你能告诉我如何在我所问的场景中进行 bulkWrite 吗?

标签: arrays node.js mongodb mongoose


【解决方案1】:

我正在使用 Neil Lunn 的建议,因为我不需要从此查询返回的文档。

所以这里是bulkwrite:

Warehouse.bulkWrite(
  [
    {
      updateOne: {
        filter: { _id: warehouse, "articles._id": article },
        update: {
          $inc: {
            "articles.$.amount": amount
          }
        }
      }
    },
    {
      updateOne: {
        filter: { _id: warehouse,
                  "articles._id": { $exists: false }},
        update: {
          $addToSet: {
            articles: {
              _id: article,
              amount: amount,
              serialized: true
            }
          }
        }
      }
    }
  ],

不知何故,第二次更新总是被执行,即使它是一个 $addToSet,这就是我添加过滤器的原因:“articles._id”: { $exists: false }。关于如何避免这种行为的任何想法?

【讨论】:

  • 您实际上的意思是{ _id: warehouse, "articles._id": { $ne: article } },因为$exists 不能充分检查已经存在的至少一个数组项。但否则这正是你应该做的。您应该注意,在nMatchednUpdated 中,响应对象的结果将开始不同于“批处理”中的指令数。
猜你喜欢
  • 1970-01-01
  • 2014-12-07
  • 2015-05-03
  • 1970-01-01
  • 2022-01-22
  • 2019-01-18
  • 1970-01-01
  • 1970-01-01
  • 2020-11-19
相关资源
最近更新 更多