2

Another problem working with mongoose. I want to update task in document as example below. For example I want to update completed field in task with _id=1 in project with name inbox. Is it possible to do in one query?

{
    "_id" : ObjectId("5702e0c732faf57c7bb9ebe9"),
    "email" : "john@doe.me",
    "projects" : [ 
        {
            "_id" : "1",
            "name" : "inbox",
            "tasks" : [ 
                {
                    "_id" : "1",
                    "text" : "First task",
                    "labels" : [ 
                        "home", 
                        "phone"
                    ],
                    "dueDate" : "2016-03-18T11:10:00",
                    "created" : "2016-03-10T10:10:00",
                    "completed" : true
                }, 
                {
                    "_id" : "2",
                    "text" : "Second task",
                    "labels" : [ 
                        "home", 
                        "phone"
                    ],
                    "dueDate" : "2016-03-18T11:10:00",
                    "created" : "2016-03-10T10:10:00",
                    "completed" : false
                }, 
            ]
        }, 
        {
            "_id" : "2",
            "name" : "work",
            "tasks" : [ 
                {
                    "_id" : "4",
                    "text" : "Fourth",
                    "labels" : [ 
                        "home", 
                        "phone"
                    ],
                    "dueDate" : "2016-03-18T11:10:00",
                    "created" : "2016-03-10T10:10:00",
                    "completed" : false
                }
            ]
        }
    ]
}
arthurr
  • 1,135
  • 1
  • 10
  • 19

2 Answers2

4

In Mongo, it is not possible to query and update nested arrays at once. The positional $ operator, that would be needed here, does not support traversing nested arrays.

From documentation:

The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value

See this issue for more information.

panjan
  • 1,269
  • 1
  • 8
  • 9
  • finally I did what I need inside callback using forEach to look up nested arrays element and updating it – arthurr Apr 24 '16 at 19:35
0

Yes possible. You need to use positional operator. Please try this:

db.yourCollection.update({
        "_id" : ObjectId("5702e0c732faf57c7bb9ebe9"),
        'projects.tasks._id': '1'
      },
      { $set: { 'projects.tasks.$.completed': newData }}
    )
Semih Gokceoglu
  • 1,408
  • 1
  • 13
  • 21
  • I've tried this User.update( {_id: Mongoose.Types.ObjectId(userId), 'projects.tasks._id': Mongoose.Types.ObjectId(data.task._id) }, { $set: { 'projects.tasks.$.completed': data.task.completed }}, (err, data) => { console.log(data); return reply('success'); } ); but in return I got { ok: 0, n: 0, nModified: 0 } – arthurr Apr 24 '16 at 18:09
  • Many reasons might be happened. Not quite sure. I suggest that you should try this in your mongoshell first (find _id s properly or try another fields instead of _id). Also you can add another property into first paramater on update. Like 'projects._id': '1'. – Semih Gokceoglu Apr 24 '16 at 18:31
  • Or the problem might be your field type. If your 'completed' is Boolean and you send String field, mongo does not allow to modify that field. As I said, you have to try on your mongo shell first. – Semih Gokceoglu Apr 24 '16 at 18:34
  • This will not work at all. The positional operator doesn't work with multiply nested arrays, as described in panjan's answer. – Vince Bowdren Feb 28 '17 at 09:35