-1

I originally created a string refillNote that I recently decided to convert to an array of objects refillNotes (see below). So I need to copy the string value of every User's refillNote string (from the refills array of objects) into the new object.

Due to both items being nested in different layers, I am not able to take the string data and inject it into the nested object using the $set method.

Here is the User object:

{ 
   name:"Joe",
   refills: [ 
      { 
         refillNote: "original refill note",
         refillNotes: [
            { 
               note:"I need to copy the original refillNote here",
               username:"Tim"
            }
         ]
      }
   ]
}

I simply want to take the existing refillNote string value from the refills array and create a new refillNotes object and inject it into the array as seen above.

Here is the current code I am using to add the new objects to the refillNotes array, but the issue is, I am not able to take the refillNote value and set it here:

User.updateMany(
  {},
  {
    $set: {
      "refills.$.refillNotes": [
        { username: "Joe", note: "refills.$.refillNote" }
      ]
    }
  }
);

This currently adds the note as the literal string "refills.$.refillNote" so I am stuck as to where in this sequence I would be able to extract the original refillNote value and be able to use it again in this $set method. Any input would be greatly appreciated.

Edit

Ending up using a hacky older forEach solution (below), which I was avoiding, but if anyone ever comes across this post with the aggregator based mongodb solution (or lack thereof), it would be awesome.

  User.find({})
    .then(function(results) {
      return results.map(function(user) {
        user.refills.forEach(function(refill) {
          if (refill.refillNote) {
            refill.refillNotes = [
              { username: "Tim", note: refill.refillNote }
            ];
          } else {
            refill.refillNotes = [];
          }
        });
        return user.save();
      });
    })
Bogie
  • 119
  • 1
  • 9
  • See the following : https://stackoverflow.com/questions/3974985/update-mongodb-field-using-value-of-another-field – matthPen Oct 12 '19 at 20:55
  • @matthPen thanks, but that's for a simple operation without the level of nesting in my situation. The solution you see in their answers does not work here. The last section I included shows why (the values with the `$` are being taken as literals in my case). – Bogie Oct 12 '19 at 22:34
  • Do you really need refillNotes as an array of objects, inside you refills array? Which version are you using? – matthPen Oct 13 '19 at 07:04
  • @NeilLunn neither questions you marked as "duplicates" answer the question I asked, and both offer responses that I am fully aware of (as indicated above). My issue is specific to carrying the original nested data to another deeply nested array. I absolutely agree, they definitely aren't a great idea, but I took over the app from another developer am slowly transitioning things back to normal without rewriting ground up (for now). – Bogie Oct 17 '19 at 19:21

1 Answers1

2

You need to use $map to apply to each array element. Here's what you need :

db.collection.aggregate([
  {
    "$addFields": {
      "refills": {
        "$map": {
          input: "$refills",
          as: "refill",
          in: {
            refillNote: "$$refill.refillNote",
            refillNotes: [
              {
                "refillNote": "$$refill.refillNote",
                name: "Tim"
              }
            ]
          }
        }
      }
    }
  }, 
  {$out:'collection'}
])

Will write :

[
  {
    "_id": ObjectId("5a934e000102030405000000"),
    "name": "Joe",
    "refills": [
      {
        "refillNote": "original refill note",
        "refillNotes": [
          {
            "name": "Tim",
            "refillNote": "original refill note"
          }
        ]
      }
    ]
  }
]

If your refills.refillNotesd doesn't need to be an array (as it already stands in the 'refills' array), just remove the array element in the above aggreggation :

...
            refillNotes: {
                "refillNote": "$$refill.refillNote",
                name: "Tim"
              }
           } 
...
matthPen
  • 4,253
  • 1
  • 16
  • 16