0

If I have some documents inside a collection. In this format:

{posts: [{"name": "post1"},..., {"name": "postN"}]}

What is the equivalent of this function:

db.my_collection.update({}, { $set: {"posts.0.lastMod": new Date()}}, false, true)

But to update all the embedded documents instead of only position 0? I have tried doing:

db.my_collection.update({}, { $set: {"posts.lastMod": new Date()}}, false, true)

But that just gave me an error already on the first document:

WriteResult({
    "nMatched" : 0,
    "nUpserted" : 0,
    "nModified" : 0,
    "writeError" : {
        "code" : 28,
        "errmsg" : "Cannot create field 'lastMod' in element {posts: [ALL MY ARRAY WAS PRINTED HERE]"
lpares12
  • 3,504
  • 4
  • 24
  • 45

2 Answers2

1

The answer in the comments above is 99% there. This makes it a tad safer by ensuring it will only use the dotpath trick to add lastMod to an existing array of posts. If posts does not exist, without the predicate it will create a brand new single object posts which is probably not desired.

db.foo.updateMany(
    {posts: {$exists:true}},
    [
        { $addFields: { 'posts.lastMod': new ISODate() } }
    ]
);
lpares12
  • 3,504
  • 4
  • 24
  • 45
Buzz Moschetti
  • 7,057
  • 3
  • 23
  • 33
-1

Based on this documentation https://www.mongodb.com/docs/manual/reference/method/db.collection.updateMany/, you can add a aggregate pipeline to the 2nd param of updateMany, so you can try this query

db. my_collection.updateMany({},[ { $addFields: { 'posts.lastMod': new Date() } }, { $set: { } }]) because you dont want to add or update any properties else the posts.lastMod, so you can leave the $set as {}

giang7499
  • 1
  • 2
  • No, if I put the positional operator as in `posts.$.lastMod` I get: `The positional operator did not find the match needed from the query.` – lpares12 Dec 14 '22 at 17:32
  • 1
    db. my_collection.updateMany({},[ { $addFields: { 'posts.lastMod': new Date() } }, { $set: { modified: "$$NOW"} }]) plz try this – giang7499 Dec 14 '22 at 17:48
  • This does the trick, but don't really understand why the last `{ $set: { modified: "$$NOW"}}`, this just adds a "modified" field into the document. – lpares12 Dec 14 '22 at 18:03
  • honestly, I just add random fields (in this case modified with timestamp will make more sense) to trigger the updateMany function – giang7499 Dec 14 '22 at 18:38
  • But why would I want to add another field to the document? I just want to add to the subdocuments. – lpares12 Dec 15 '22 at 08:58
  • as I said before, it's just for triggering, you can run db. my_collection.updateMany({},[ { $addFields: { 'posts.lastMod': new Date() } }, { $set: { } }]) – giang7499 Dec 16 '22 at 09:10
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – turivishal Dec 18 '22 at 07:22