1

背景:我正在开发一个显示库存管理分析的应用程序。它上传了一个办公室 EXCEL 文件,并随着文件上传,应用程序将其转换为 JSON 数组。然后,它将每个 json 对象与 DB 中的对象进行关联,根据 XLS 文件更改其数量,并将时间戳添加到包含数量更改的 stamps 数组中。

例如:

{"_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

...
}
4

2 回答 2

0

您可以使用 mongoose 的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);
});
于 2019-01-22T09:52:09.650 回答
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)

})()
于 2019-01-22T09:58:59.453 回答