MongoDB-找到一个并添加一个新属性

时间:2019-01-22 09:15:17

标签: node.js database mongodb mongoose

背景:我正在开发一个显示库存管理分析的应用程序。 它会上传一个Office EXCEL文件,当文件上传时,应用会将其转换为JSON数组。然后,它将每个json对象与数据库中的对象进行映射,根据XLS文件更改其数量,并向包含数量变化的图章数组添加时间戳。

例如:

{"_id":"5c3f531baf4fe3182cf4f1f2",
"sku":123456,
"product_name":"Example",
"product_cost":10,
"product_price":60,
"product_quantity":100,
"Warehouse":4,
"stamps":[]
}

XLS上传后,假设我们售出了10个单位,看起来应该像这样:

{"_id":"5c3f531baf4fe3182cf4f1f2",
"sku":123456,
"product_name":"Example",
"product_cost":10,
"product_price":60,
"product_quantity":90,
"Warehouse":4,
"stamps":[{"1548147562": -10}]
}

现在我找不到适合mongoDB的命令,我正在Node.js和Angular中开发,很想阅读一些想法。

for (let i = 0; i < products.length; i++) {
 ProductsDatabase.findOneAndUpdate(
      {"_id": products[i]['id']},
      //CHANGE QUANTITY AND ADD A STAMP

...
}

2 个答案:

答案 0 :(得分:0)

您可以使用猫鼬的findOneAndUpdate更新文档的现有值。

"use strict";


const ids = products.map(x => x._id);

let operations = products.map(xlProductData => {

  return ProductsDatabase.find({
    _id: {
      $in: ids
    }
  }).then(products => {

    return products.map(productData => {
      return ProductsDatabase.findOneAndUpdate({
        _id: xlProductData.id // or product._id
      }, {
        sku: xlProductData.sku,
        product_name: xlProductData.product_name,
        product_cost: xlProductData.product_cost,
        product_price: xlProductData.product_price,
        Warehouse: xlProductData.Warehouse,
        product_quantity: productData.product_quantity - xlProductData.product_quantity,

        $push: {
          stamps: {
            [new Date().getTime()]: -1 * xlProductData.product_quantity
          }
        },

        updated_at: new Date()
      }, {
        upsert: false,
        returnNewDocument: true
      });
    });

  });

});

Promise.all(operations).then(() => {
  console.log('All good');
}).catch(err => {
  console.log('err ', err);
});

答案 1 :(得分:0)

您需要在此处进行两项操作。首先将是从数据库中获取与JSON数组中的文档匹配的文档数组。从列表中比较'product_quantity'键,如果有更改,请创建一个具有产品ID和数量变化的新对象数组。

第二个操作将是更新,该更新使用此新阵列并更改每个匹配产品的数量。

借助此一系列新的更新的产品属性,非常适合对此进行批量更新,例如遍历列表并发送 对服务器的每次更新请求都可能在计算上昂贵。

请考虑使用模型上的bulkWrite方法。这接受一个数组的写操作并执行每个写操作,其中一个典型的更新操作 您的用例将具有以下结构

{ updateOne :
    {
    "filter" : <document>,
    "update" : <document>,
    "upsert" : <boolean>,
    "collation": <document>,
    "arrayFilters": [ <filterdocument1>, ... ]
    }
}

因此您的操作将遵循以下模式:

(async () => {

    let bulkOperations = []
    const ids = products.map(({ id }) => id)
    const matchedProducts =  await ProductDatabase.find({ 
        '_id': { '$in': ids }
    }).lean().exec()

    for(let product in products) {
        const [matchedProduct, ...rest] = matchedProducts.filter(p => p._id === product.id)
        const { _id, product_quantity } = matchedProduct
        const changeInQuantity = product.product_quantity - product_quantity

        if (changeInQuantity !== 0) {
            const stamps = { [(new Date()).getTime()] : changeInQuantity }

            bulkOperations.push({
                'updateOne': {
                    'filter': { _id },
                    'update': { 
                        '$inc': { 'product_quantity': changeInQuantity },
                        '$push': { stamps }
                    }
                }
            })
        }
    }

    const bulkResult = await ProductDatabase.bulkWrite(bulkOperations)
    console.log(bulkResult)

})()