2

Consider the following mongo data:

{ _id: "1",
  names: ["John", "Peter"]
}

What is the correct way to replace a simple element in the array, getting the following result ?

{ _id: "1",
  names: ["John", "Sarah"]
}

In my code I receive a function to exchange "Peter" with "Sarah", like:

substituteItemOnArray = (id, from, to) => {
   MyModel.update({
      id: id
   },
   {
      ??? What is the correct way to substitute one element with another ???
   });

}

substituteItemOnArray("1", "Peter", "Sarah");
Ashh
  • 44,693
  • 14
  • 105
  • 132
Mendes
  • 17,489
  • 35
  • 150
  • 263
  • does `names` is an array of strings? something like `names: ["John", "Peter"]`. **I believe data is also type of array** – Prasad Telkikar Feb 21 '19 at 13:21
  • Yes! I will correct in code... – Mendes Feb 21 '19 at 13:21
  • https://docs.mongodb.com/manual/reference/operator/update/positional-filtered/#positional-update-arrayfilters – Jonas Wilms Feb 21 '19 at 13:22
  • Possible duplicate of [How to Update Multiple Array Elements in mongodb](https://stackoverflow.com/questions/4669178/how-to-update-multiple-array-elements-in-mongodb) – Daksh M. Feb 21 '19 at 13:25
  • Possible duplicate of [MongoDB Replace specific array values](https://stackoverflow.com/questions/48545448/mongodb-replace-specific-array-values) – dnickless Feb 21 '19 at 20:33

3 Answers3

1

I don't know any way to do it with just Mongo operators.

I think you will have to retrive the document by id, find the index of the string you want to replace and only after that update document

Below function should do what I described above

async substituteItemOnArray = (_id, from, to) => {
    const doc = await MyModel.findOne({  _id  });
    if (doc && doc.names && doc.names.indexOf(from) > -1) {

    const index = dox.names.indexOf(from); 
    const keyToUpdate = `names.${index}`;
    MyModel.update({ _id }, { $set: { [keyToUpdate] : to} },)
}

substituteItemOnArray("1", "Peter", "Sarah");
Arif
  • 1,617
  • 9
  • 18
1

You can do this with mongoDB arrayFilters like this in mongoose:

function substituteItemOnArray = (id, from, to) {
  return MyModel.findOneAndUpdate(
    {id: id}, // where to update
    {$set: {'names.$[element]': to }}, // what to update
    {arrayFilters: [{'element': from}]} // what should match in array.
  )
}

(
  async () => {
    let doc = await substituteItemOnArray(id, "Peter", "Sarah");
    console.log(doc);
  }
)()
Daksh M.
  • 4,589
  • 4
  • 30
  • 46
1

Simply use $ positional operator

db.getCollection('test').findOneAndUpdate(
  { names: "Peter" },
  { $set: { 'names.$': "Sarah" }}
)
Ashh
  • 44,693
  • 14
  • 105
  • 132