antoniopresto / react-native-local-mongodb

react-native local mongodb storage.
MIT License
304 stars 66 forks source link

How to update existing object in array ? #72

Open abdullahIsa opened 2 years ago

abdullahIsa commented 2 years ago

Hello, thanks very much for this but I am looking for how to update an existing object in an array based on a value or query check, how can I get this done as $addToSet with db.update() is pushing a new one because the _id are different and if I am correct as stated in the documentation it should replace the old object, so may I know what I am doing wrong or how may I add an additional query to update this, thanks very much.

Example:

Old object in the array

[{
   "_id":"Z5VhCLnr6Pfq",
   "date":"2022-01-30T09:22:01+08:00",
   "filesData":"undefined",
   "idOfMessage":"Z5VhCLnr6Pfq",
   "is_new_message":true,
   "message":"T",
   "messageValue":"T",
   "message_Replied":null,
   "replied_Message":false,
   "seenByRoomUsers":[

   ],
   "sender":"61f58a8c1135f66c28af454a",
   "sub_id":"Z5VhCLnr6Pfq",
   "successfullySent":false,
   "time":"9:22 AM",
   "typeOfMessage":{
      "texts":true
   }
}]

New object coming from the server containing additional information that should replace or update the old one

{
   "_id":"61f5e8386327bd1fa8d3e3fc",
   "date":"2022-01-30T09:22:01+08:00",
   "filesData":[

   ],
   "is_new_message":false,
   "message":"T",
   "messageUrl":"room/61f5aa8733657d5cc8445ad9/group/false/discussion/false/messsage/61f5e8386327bd1fa8d3e3fb",
   "messageValue":"T",
   "message_Replied":{
      "filesData":[
         "Array"
      ]
   },
   "message_forWarded":[

   ],
   "replied_Message":false,
   "seen":false,
   "seenByRoomUsers":[

   ],
   "sender":"61f58a8c1135f66c28af454a",
   "sub_id":"Z5VhCLnr6Pfq",
   "successfullySent":true,
   "time":"9:22 AM",
   "typeOfMessage":{
      "texts":true
   }
jwh-hutchison commented 2 years ago

This is assuming that you mean to update a specific array field's array item of an object belonging to your your datastore. It's not pretty nor the most efficient but maybe something like (getting the pre-existing item might be the easiest way):

db.findOne(
  {_id: idOfObjectToUpdate},
  function (err, doc) {
    if (!err) {
      const originalEntryOfArray = doc[arrayFieldToUpdate].filter(item => item._id === replacementArrayItem._id)[0]

      db.update(
    {_id: idToUpdate},
        {[arrayFieldToUpdate]: doc[arrayFieldToUpdate]
        .filter(item => item._id !== replacementArrayItem._id) // id of array item you want to replace
            .concat([{...originalEntryOfArray, ...replacementArrayItem }]) // the replacement goes here so the fields that need to be updated overwrite those of 'originalEntryOfArray'
        }},
        {upsert: upsert},
        function (err, numAffected) {
          resolve(!err);
        },
      );
    }
  },
);