Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

findOneAndUpdate nested object in array

Trying to use findOneAndUpdate() to change an object inside an array within MongoDB. The documentation for mongoDB's nodeJS driver isn't clear to me. The document looks like this:

{
  _id:ObjectID(),
  some: string,
  body: string,
  steps:[
   [0]{name: "foo", state:"Q"},
   [1]{name: "bar", state:"Q"},
   [n]{name: "fooBar", state:"Q"}
 ]
}

I need to lookup the steps name (foo) and set it's state to P (for in progress) and then to C (for complete) when the task has been executed or E when it errors.

I'll then need to also grab the name of the next step to.

Finding the document isn't hard as I will have the _id already, it's the update portion that's getting me.

EDIT: This is what I've got so far

  async msg => {
    const _id = msg.content.toString();
    const id = new objectId(_id);
    logger.info(`${name} consumer - Recieved new task, fetching details`, {
      id
    });
    try {
      const jobDetails = await collection.findOneAndUpdate(
        { _id: id },
        {
          /**/
        }
      );
      await consumer.task(jobDetails);
    } catch (e) {}
  },

It's the framework for a rabbitMQ consumer

like image 547
Alistair Hardy Avatar asked Jun 10 '19 13:06

Alistair Hardy


1 Answers

I don't know how would you choose wich letter to set - P, C or E, because it is not quite clear, but for replacing a value in mongoDB it would look like this (let's say for 'P'):

myCollection.findOneAndUpdate({"_id": docId, "steps.name": "foo"},
    {$set: {"steps.$.state": "P"}})
  1. Find the document you need to change.
  2. Find the object inside the array "steps.name": "foo". And you get the position of that object in array.
  3. You're setting new value for the object's property ( $ reflects the position).
like image 73
Daniyal Lukmanov Avatar answered Oct 12 '22 22:10

Daniyal Lukmanov