0

I have a simple collection with a document like this one:

{
    _id: ObjectId('62b196e43581370007773393'),
    name: 'John',
    jobs: [
        {
            company: 'ACME',
            type: 'programmer',
            technologies: [
                {
                    level: 1,
                    name: 'Java'
                },
                {
                    level: 3,
                    name: 'MongoDB'
                }
            ]
        }
    ]
}

I'd like to collect all technologies into a new field in the "job" sub-document for "programmers" jobs only, to achieve this effect:

(...)
jobs: [
 { 
   it_technologies : ["Java", "MongoDB"]
   (...)

 }
]
(...)

The problem is that I do not know how to refer to and collect proper elements of the documents with this query:

db.runCommand({update: "employees",      
    updates: [
         {
           q: {},
           u: { $set: { "jobs.$[j].it_technologies": "<how to collect all technologies in this job?>" } },
           upsert: false,
           multi: true,
           arrayFilters: [{
            $and:
              [
                {"j.type": "programmer"},
                {"j.technologies": {$exists : true, $ne: []} }
              ]
            }]
         }
      ] });

Is it at all possible? I'd be grateful for any clue!

1 Answer 1

2

Think that you need to work the update with the aggregation pipeline.

  1. map - Iterate with the jobs array and return a new array.

    1.1. $cond - Check the condition (Match the current document of jobs type and technology is not an empty array). If fulfilled, then update the document, else remains existing.

    1.1.1. $mergeObjects - Merge current document with the document with it_technologies.

db.collection.update({},
[
  {
    $set: {
      "jobs": {
        $map: {
          input: "$jobs",
          in: {
            $cond: {
              if: {
                $and: [
                  {
                    $eq: [
                      "$$this.type",
                      "programmer"
                    ]
                  },
                  {
                    $ne: [
                      "$$this.technologies",
                      []
                    ]
                  }
                ]
              },
              then: {
                $mergeObjects: [
                  "$$this",
                  {
                    it_technologies: "$$this.technologies.name"
                  }
                ]
              },
              else: "$$this"
            }
          }
        }
      }
    }
  }
],
{
  upsert: false,
  multi: true,
  
})

Sample Mongo Playground

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

1 Comment

It is quite complex but it works! Thank you very much!

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.