0

For example, if a purchase order has line items like this:

enter image description here

and user from the client side send us line items to be updated in an array called lineItemsToUpdate and has a format like this:

[
{       unitCost: 342,
        totalQuantity: 13,
        acceptedQuantity: 6,
        rejectedQuantity: 18,
        title: 'Unbranded Concrete Pizza',
        description: 'Soft',
        variant: 5f2d5eb0195026e6dd549ef0 },
      { unitCost: 189,
        totalQuantity: 95,
        acceptedQuantity: 49,
        rejectedQuantity: 16,
        title: 'Handcrafted Rubber Cheese',
        description: 'Assurance',
        variant: 5f2d5eaf195026e6dd549b7d },
      { unitCost: 267,
        totalQuantity: 18,
        acceptedQuantity: 93,
        rejectedQuantity: 11,
        title: 'Incredible Soft Car',
        description: 'solution-oriented',
        variant: 5f2d5eb0195026e6dd549d3d },
]

here in the lineItemsToUpdate array, it's possible that the value of each element has been changed by the client and I want to update all the matching element by variant field in my sub-document if I describe it in the format of a user story:

update all lineItems "fields" according to lineItemsToUpdate array where the lineItemsToUpdate.[elem].variant === linitem.[elem].variant using $set, if possible $each and arrayFilters operators

I read some example through the mongodb documentation like this one:

db.students2.update(
   { },
   { $set: { "grades.$[elem].mean" : 100 } },
   {
     multi: true,
     arrayFilters: [ { "elem.grade": { $gte: 85 } } ]
   }
)

but the problem in here { $set: { "grades.$[elem].mean" : 100 } } is that the 100 value is constant and I want this part dynamic as I described in above.

1 Answer 1

0

Following is JS function you have to take help of.

function(c1,arr2){
    var arr1 = c1.next().lineItems;
    for(i=0;i<arr1.length;i++){
        for(j=0;j<arr2.length;j++){
            if(arr1[i].variant===arr2[j].variant){
                db.purchaseOrder.update(
                { },
                { $set: { "lineItems.$[elem].unitCost" : arr2[j].unitCost,"lineItems.$[elem].totalQuantity" : arr2[j].totalQuantity } .....},
                { multi: true,
                  arrayFilters: [ { "elem.variant": { $eq: arr2[j].variant } } ]
                }
                )
            }
        }
    }
}

Explanation

  1. We have to pass 2 parameters: i) Mongo cursor and ii) An array. Cursor is the collection to be updated. For your case, it is Purchase Order. Array is lineItemsToUpdate array here.

  2. Next we take 2 for loops to match variant field between cursor and array.

  3. If there is a match, we update the Purchase Order using update command and $set operator.

Execution

  1. Go to your Mongo Shell. Ensure the current database has Purchase Order collection.

  2. Define modifyItems function as below.

    var modifyItems=function(c1,arr2){  
        var arr1 = c1.next().lineItems;  
        for(i=0;i<arr1.length;i++){  
            for(j=0;j<arr2.length;j++){  
                if(arr1[i].variant===arr2[j].variant){  
                    db.purchaseOrder.update(  
                    { },  
                    { $set: { "lineItems.$[elem].unitCost" :     arr2[j].unitCost,"lineItems.$[elem].totalQuantity" : arr2[j].totalQuantity }...    },  
                    { multi: true,  
                      arrayFilters: [ { "elem.variant": { $eq:   arr2[j].variant } } ]  
                    }  
                    )  
                }  
            }  
        }  
    }  
    
  3. Define a variable arr which contains lineItemsToUpdate.

    var arr=[  
          { unitCost: 342,  
            totalQuantity: 13,  
            acceptedQuantity: 6,  
            rejectedQuantity: 18,  
            title: 'Unbranded Concrete Pizza',  
            description: 'Soft',  
            variant: 5f2d5eb0195026e6dd549ef0 },  
          { unitCost: 189,  
            totalQuantity: 95,  
            acceptedQuantity: 49,  
            rejectedQuantity: 16,  
            title: 'Handcrafted Rubber Cheese',  
            description: 'Assurance',  
            variant: 5f2d5eaf195026e6dd549b7d },  
          { unitCost: 267,  
            totalQuantity: 18,  
            acceptedQuantity: 93,  
            rejectedQuantity: 11,  
            title: 'Incredible Soft Car',  
            description: 'solution-oriented',  
            variant: 5f2d5eb0195026e6dd549d3d }  
    ]  
    
  4. Now execute the JS function.

    modifyItems(db.purchaseOrder.find({},{"lineItems":1,"_id":0}),arr);  
    

If there is no error, your Purchase Order line items will be now updated with the array values in one single shot.

Sign up to request clarification or add additional context in comments.

2 Comments

I can do this by bulk write very easily. I want a solution in an efficient and modern way your solution if there is 100 line items this will make 100 mongo connection why should I not use bulk write instead of this also I mentioned in question title at "once" word.
100 mongo connections? It is single connection and 100 db requests. Considering you want to update with dynamic values(as you mentioned in your question, update query), it can't be done easily by bulk write, I think. Also my solution is as specified by your user story in question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.