Py学习  »  MongoDB

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

Elad Dahan • 4 年前 • 686 次点击  

背景:我正在开发一个应用程序,显示库存管理的分析。 它获取一个上传的office EXCEL文件,当文件上传时,应用程序将其转换为一个json数组。然后,它将每个json对象与数据库中的对象合并,根据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

...
}
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/50866
 
686 次点击  
文章 [ 2 ]  |  最新文章 4 年前
Sridhar
Reply   •   1 楼
Sridhar    5 年前

你可以用猫鼬的 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);
});
chridam
Reply   •   2 楼
chridam    5 年前

你需要在这里做两次手术。第一种方法是从数据库中获取与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)

})()