StackThis
StackThis

Reputation: 883

What is the correct syntax for $set of an array element of an embedded doc?

Right now, Mongo is skipping over this update because of a syntax error. And when I try different placements for the $.to. (like replies.$.to), this results: [MongoError: cannot use the part (to of replies.0.to.read.marked) to traverse the element..]

How should the $set be edited:

Models.Message.findOneAndUpdate(

  { "replies._id": ObjectId("53dd4b67f0f23cad267f9d8b"), "replies.to.username": "UserA" },
  {
    "$set": { 
        "$.to.read.marked": true,
        "$.to.read.datetime": req.body.datetimeRead,
        "$.to.updated": req.body.datetimeRead
    }
  },

To $set to.read.marked:true for userA of the specific reply:

{
    "_id" : ObjectId("53daf26af7b70fd82ffd4cff"),
    "updated" : ISODate("2014-08-02T20:36:03.000Z"),
    "message" : "here's a message",
    "replies" : [ 
        {
            "reply" : "here's a reply",
            "created" : 1407011687000,
            "_id" : ObjectId("53dd4b67f0f23cad267f9d8b"),
            "to" : [ 
                {
                    "username" : "userA",
                    "updated" : ISODate("2014-08-02T20:34:47.000Z"),
                    "_id" : ObjectId("53dd4b67f0f23cad267f9d8c"),
                    "read" : {
                        "datetime" : ISODate("2014-08-02T20:34:47.000Z"),
                        "marked" : false
                    }
                },
                {
                    "username" : "userB",
                    "updated" : ISODate("2014-08-02T20:34:47.000Z"),
                    "_id" : ObjectId("53dd4b67f0f23cad267f9d8d"),
                    "read" : {
                        "datetime" : ISODate("2014-08-02T20:34:47.000Z"),
                        "marked" : false
                    }
                }
            ]
        }, 
        {
            "reply" : "here's another reply",
            "created" : 1407011763000,
            "_id" : ObjectId("53dd4bb3a9f9497e270525cb"),
            "to" : [ 
                {
                    "username" : "userA",
                    "updated" : ISODate("2014-08-02T20:36:03.000Z"),
                    "_id" : ObjectId("53dd4bb3a9f9497e270525cc"),
                    "read" : {
                        "datetime" : ISODate("2014-08-02T20:36:03.000Z"),
                        "marked" : false
                    }
                },
                {
                    "username" : "userB",
                    "updated" : ISODate("2014-08-02T20:36:03.000Z"),
                    "_id" : ObjectId("53dd4bb3a9f9497e270525cd"),
                    "read" : {
                        "datetime" : ISODate("2014-08-02T20:36:03.000Z"),
                        "marked" : false
                    }
                }
            ]
        }
    ],
    ...
}

Upvotes: 0

Views: 563

Answers (1)

ma08
ma08

Reputation: 3744

You can't use $ for nested arrays. So you can't use update at all. Follow this issue.

So you will need to make a find query for replies._id and proceed to get the index/indexes manually.

An ugly option would be to

Models.Message.findOne({ "replies._id":ObjectId("53dd4b67f0f23cad267f9d8b", "replies.to.username": "UserA")},
   function(err,doc){
       if(doc){
       //use a for loop over doc.replies to find the index(index1) of ObjectId("53dd4b67f0f23cad267f9d8b") at replies[index]._id
       var index1;
       for(var i=0;i<doc.replies.length;i++){
          if(doc.replies[i]._id === ObjectId("53dd4b67f0f23cad267f9d8b")){
             index1=i;
             break;
          }
        }
        var index2;
       //use a for loop over doc.replies[index1].to and find the index(index2) of "UserA" at replies[index1].to[index2]
       for(var j=0;j<doc.replies[index1].to.length;j++){
         if(doc.replies[index1].to[index2].username==="UserA"){
            index2=j;
            break;
         }
       } 

       doc.replies[index1].to[index2].read.marked = true;
       doc.replies[index1].to[index2].read.datetime = req.body.datetimeRead;
       doc.replies[index1].to[index2].updated= req.body.datetimeRead;
       doc.markModified('replies')
       doc.save(function(err,doc2){...})
     }
   });

Upvotes: 1

Related Questions