Shift all elements of an array field to another array field throughout the whole collection

I have a collection with documents like the following (other fields excluded):

"array" : [
    ObjectId("..."),
    ObjectId("..."),
    ObjectId("...),
    ObjectId("...")
],
"anotherArray" : [ ],

I want all the documents to be updated to this:

"array" : [],
"anotherArray" : [ 
    ObjectId("..."),
    ObjectId("..."),
    ObjectId("...),
    ObjectId("...")
],

Is there a solution using aggregation or something simpler?

Note:

  1. All the documents have different number of elements.
  2. In each document, everything in the array needs to be shifted to anotherArray.
  3. All the documents need to be updated.

What have you tried so far?

What are the issues you faced?

Real documents would be better because we cannot cut-n-paste documents like

in our environment because the object ids are wrong.

I have two things in mind but am unable to figure out the syntax.

  1. Storing the array as a variable (let’s say temp), applying a { $pull : { array: true } } on array and doing a { $set: { anotherArray: temp } }.

  2. Using the $map to transform all the documents.

Here’s a document with some actual ObjectIds:

{
    "appliedProfiles" : [
        ObjectId("614f1e494d79516793413353"),
        ObjectId("613a4489c2fec521e5af8a4a"),
        ObjectId("613a08efc2fec521e5af8a18"),
        ObjectId("613a3fd4c2fec521e5af8a44")
    ],
    "selectedProfiles" : [],
}

Hope that makes things clearer.

I have not tested it but you could try:

{
  "$set" :
  {
     "selectedProfiles" : "$appliedProfiles" ,
     "appliedProfiles" : []
  }
}

Oh, well. That’s a lot simpler. Silly me.

All the selectedProfiles are not empty though so I think I need to try something like:

{
  "$addToSet": { selectedProfiles: { $each: "$appliedProfiles" } } 
  "$set" :  { "appliedProfiles" : []  }
}

Let me try it on a duplicate collection and get back to you.

1 Like

This gave me the following error:

The argument to $each in $addToSet must be an array but it was of type string

I did find this SO question: mongodb - Atomically move object by ID from one array to another in same document - Stack Overflow

But in my case there’s no conditional shifting but total shifting.

I solved it using a pipeline inside update command:

db.teamupparticipants.update(
    { },
    [{
        "$set": {
            selectedProfiles: {
                $map: {
                    input: "$appliedProfiles",
                    as: "profile",
                    in: "$$profile"
                }
            },
            appliedProfiles: []
        },
    }],
    { multi: true }
)

Make sure to include the update query inside an array so as to make it a pipeline.

1 Like

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.