skip to Main Content

i’m kinda new at develping apps with nodejs and mongoose, i’m trying to update an array of numbers by modifying a single value inside it but i can’t find the correct way to do it.

this is the document:

{ 
id:5,
arrayOfValues:[2,3,4,5]
}

Let’s say i receive a value of 10 that must be stored in position 1, the desired outcome is:

{ 
id:5,
arrayOfValues:[2,10,4,5]
}

I thought about using model.findOne() and then model.updateOne() but since this operation could be done several times per minute i was searching for a more efficient method.

Edit: This is my current typescript code:

const filter = {'id':receivedMessage.id};
const options = {upsert:true, includeResultMetadata: true};


const foundDocument = await myModel.findOne(filter);

if(foundDocument){
    let tempArray = foundDocument.myArray;
    let position = receivedMessage.k;
    let value = receivedMessage.v

    tempArray[position] = value

    await myModel.updateOne(filter, {myArray: tempArray}, options);
}

What is the correct way to update only that single element of the array?

2

Answers


  1. You can simplify the update operation by directly using Mongoose updateOne method with the $set operator. Here’s the simplified version of your update operation, without the need to retrieve the document first:

    const filter = { id: receivedMessage.id };
    await myModel.updateOne(
      filter,
      { $set: { [`arrayOfValues.${receivedMessage.k}`]: receivedMessage.v } }
    );
    
    Login or Signup to reply.
  2. There is no correct way. However, MongoDB recommends the use of its $push operator for adding elements to an array. In your case you can leverage a couple of the $push modifiers to insert your new value at the specified array index with $position and $each like so:

    const doc = await myModel.findOneAndUpdate({ id:receivedMessage.id },
    {
      $push: {
        arrayOfValues: {
          $each: [
            receivedMessage.k // the value you want to insert
          ],
          $position: receivedMessage.v // the array index of where to insert
        }
      }
    }, {new: true});
    

    Notes:

    1. Although $each is typicality used to push multiple elements to an array, the $position modifier can only be used in combination with $each. The $each will only have to push in one value to arrayOfValues which is perfectly fine.
    2. The Model.findOneAndUpdate is more efficient than the Model.findOne + Model.updateOne given that it performs the update in one database call as opposed to two. It’s also atomic so in theory another client can’t modify the document while you’re updating it with findOneAndUpdate. The same isn’t true with a findOne + updateOne because Node.js is asynchronous so the event loop handles other requests while it awaits the first findOne call to be resolved/rejected.
    3. const doc will return null if no document was found because Model.findOneAndUpdate either returns the document or returns null (or fails of course).
    4. The {new:true} option simply means return the document with the new changes made to it.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search