Tengo una colección con muchos documentos que contienen precios de envío:
{ "_id": { "$oid": "5f7439c3bc3395dd31ca4f19" }, "adapterKey": "transport1", "pricegrid": { "10000": 23.66, "20000": 23.75, "30000": 23.83, "31000": 43.5, "40000": 44.16, "50000": 49.63, "60000": 50.25, "70000": 52, "80000": 56.62, "90000": 59, "100000": 62.5, "119000": 68.85, "149000": 80, "159000": 87, "179000": 94, "199000": 100.13, "249000": 118.5, "299000": 138.62, "999000": 208.63 }, "zones": [ "25" ], "franco": null, "tax": 20, "doc_created": { "$date": "2020-09-30T07:54:43.966Z" }, "idConfig": "0000745", "doc_modified": { "$date": "2020-09-30T07:54:43.966Z" } } En pricegrid , todas las propiedades pueden ser diferentes de una grilla a otra.
Me gustaría actualizar todos los precios en el campo "pricegrid" (precio * 1.03 + 1).
Intenté esto:
db.shipping_settings.updateMany( { 'adapterKey': 'transport1' }, { $mul: { 'pricegrid.$': 1.03 }, $inc: { 'pricegrid.$': 1} } )Dando como resultado este error:
MongoServerError: Updating the path 'pricegrid.$' would create a conflict at 'grille.$'Así que probé con solo $mul (planeando hacer $inc en otra consulta):
db.livraison_config.updateMany( { 'adapterKey': 'transport1' }, { $mul: { 'pricegrid.$': 1.03 } } )Pero en ese caso, me sale este error:
MongoServerError: The positional operator did not find the match needed from the query.¿Podría indicarme la forma correcta de escribir la solicitud?
Puede usar una canalización de agregación en una actualización. $objectToArray pricegrid para convertirlo primero en una matriz de tupla kv. Luego, haz un $map para realizar el cálculo. Finalmente, $arrayToObject para volver a convertirlo.
db.collection.update({ "adapterKey": "transport1" }, [ { $set: { pricegrid: { "$objectToArray": "$pricegrid" } } }, { "$set": { "pricegrid": { "$map": { "input": "$pricegrid", "as": "p", "in": { "k": "$$pk", "v": { "$add": [ { "$multiply": [ "$$pv", 1.03 ] }, 1 ] } } } } } }, { $set: { pricegrid: { "$arrayToObject": "$pricegrid" } } } ])Aquí está el parque infantil de Mongo para su referencia.
Puedes hacerlo con el marco de agregación:
$objectToArray : para transformar el objeto de cuadrícula de precios en una matriz para que pueda iterar sus elementos$map para iterar sobre la matriz generada en el paso anterior$sum y multiply para realizar operaciones matemáticas$arrayToObject para transformar la matriz actualizada de nuevo en objeto db.collection.update({ "adapterKey": "transport1" }, [ { "$set": { "pricegrid": { "$arrayToObject": { "$map": { "input": { "$objectToArray": "$pricegrid" }, "in": { k: "$$this.k", v: { "$sum": [ 1, { "$multiply": [ "$$this.v", 1.02 ] } ] } } } } } } } ], { "multi": true })Puede que me equivoque, pero parece que actualmente no hay soporte para esta función; en realidad, hay un problema de Jira abierto que aborda este tema. Sin embargo, no parece que esto vaya a implementarse.