0

If I have a document like this:

db.people.insertOne({name: "Annie", latestScore: 5});

Then based on this answer, I am able to move latestScore to an array field like this:

db.people.updateOne(
    {name: 'Annie'},
    [
        {$set: 
            {scoreHistory: 
                {$concatArrays: [
                    {$ifNull: ["$scoreHistory", []]},
                    ["$latestScore"]
                ]}
            }
        }, 
        { $unset: ["latestScore"] }
    ]
);

This is the resulting document:

{
  _id: ObjectId("61d2737611e48e0d0c30b35b"),
  name: 'Annie',
  scoreHistory: [ 5 ]
}

Can we perform the same update to objects nested in an array? For example, if the document is like this:

db.people.insertOne({
    name: 'Annie',
    words: [
        {word: "bunny", score: 5},
        {word: "pink", score: 5}
    ]
});

How can we update it to this:

{
    name: 'Annie',
    words: [
        {word: "bunny", scoreHistory: [5]},
        {word: "pink", scoreHistory: [5]}
    ]
}

I know I can iterate and modify the array from the app and update the whole array at once, but I would like to do it using operators like in the first example above.

The website first displays words.word and words.score in rows, clicking on a row shows words.scoreHistory in a popup. I am expecting words array to be less than 500. Any advise on remodelling the schema to simplify the above operation is also welcome!

Andrew Nessin
  • 1,206
  • 2
  • 15
  • 22

1 Answers1

2
db.collection.update({
  name: "Annie"
},
[
  {
    $set: {
      words: {
        $map: {
          input: "$words",
          as: "m",
          in: {
            word: "$$m.word",
            scoreHistory: {
              $concatArrays: [
                {
                  $ifNull: [
                    "$$m.scoreHistory",
                    []
                  ]
                },
                [
                  "$$m.score"
                ]
              ]
            }
          }
        }
      }
    }
  }
])

mongoplayground

YuTing
  • 6,555
  • 2
  • 6
  • 16
  • This query overrides history on every update; a modification was required to make the `scoreHistory` field actually behave like a history by preserving values - [mongoplayground - preserve history](https://mongoplayground.net/p/K6piy847ELm). SO is not allowing me to suggest this as an edit as the edit queue is full. – Andrew Nessin Jan 03 '22 at 06:38
  • @AndrewNessin I update my answer with your suggest – YuTing Jan 03 '22 at 06:59