1

I am having trouble to understand how to update tags array within an object of arrays in mongoDB.

I have an array of objects and its corresponding ObjectID of which tags I would like to update on mongoDB. What I tried is to use a loop using updateOne specifying the ObjectID as a query to find the respective Document.

Something like this:

nodes.forEach(node => {
   const query = { '_id' : ObjectId(node.Id) }

   db.collection(collection).updateOne(
      query,
      { $set: { 'tags': value } },
      function(err, result) {
        if (err) {
            throw err;
        }
        console.log(result);
     });
  });

This did not work unfortunately. I have tried other approaches but I could not find anything that works

I have the following mongodb data structure:

{
"_id": {
  "$oid": "6022bc9f9b55276bd39f4e0"
},
"name": "TestProject",
"projectData": {
  "nodes": [
    {
      "data": {
        "_id": {
          "$oid": "6022bc959b559276bd39f4be"
        },
        "nodeData": {
          "tags": []
        }
      }
    },
    {
      "data": {
        "_id": {
          "$oid": "7022bc959b559276bd39f4ce"
        },
        "nodeData": {
          "tags": []
        }
      }
    },
    {
      "data": {
        "_id": {
          "$oid": "8022bc959b559276bd39f4de"
        },
        "nodeData": {
          "tags": []
        }
      }
    }
  ....
  ]
}

I would like to update only specific tags of objects which match the ones that I pass in as an ObjectID. What would be the best approach to update a bunch of object values matching a specific ObjectID?

2 Answers 2

1

You can use, the filtered positional operator $[<identifier>] identifies the array elements that match the arrayFilters conditions for an update operation.

  • If you are updating same tags in each node id than try $in condition other wise you can use bulkWrite() operation.
let value = ["tag1", "tag2"];
let nodes = [
  ObjectId("6022bc959b559276bd39f4be"),
  ObjectId("7022bc959b559276bd39f4ce")
];

db.collection(collection).updateOne(
  {},
  { $set: { "projectData.nodes.$[d].data.nodeData.tags": value } },
  {
    arrayFilters: [
      { "d.data._id": { $in: nodes } }
    ]
  }
)

Playground

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

2 Comments

The tag content can be different per node, how would I do this in a bulkWrite operation?
Thanks! I tried this solution, and it works fine!
1

For completeness sake, I want to add my own solution to this. Based on accepted answer, I build the following operation, since each node might have different tags and I wanted to be able to add to the tags each time:

const ObjectID = require('mongodb').ObjectID;

nodes.forEach(node => {
  updateOneObjectWithTags(db, node._id, "projectData.nodes.$[d].data.nodeData.tags", node.nodeData.tags, "d.data._id", collection).then(result => {
    console.log(result);
  });
});


updateOneObjectWithTags: (db, objectId, updateKey, updateValue, arrayFilterKey, collection) => {
  return new Promise((resolve, reject) => {
    db.collection(collection).updateOne(
    {},
    {
      $set: {
        [updateKey] : updateValue
      }
    },
    {
      arrayFilters: [
        {
          [arrayFilterKey]: new ObjectID(objectId)
        }
      ]
    })
    resolve(true);
  });

Comments

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.