5

As it stands, I am able to get this functionality working using the Mongo shell, but having issues with the nested arrays inside of Node.js using Mongoose.

Mongo shell command that is successful:

db.test.update({}, {$set: {"this.$[i].that.$[x].amnt": 10000}}, {arrayFilters: [{"i._id": ObjectId('5a568059bc44142a9ca33d09')}, {"x.userId": ObjectId('5a466acb864c752f8c9890c6')}]})

Result: changed the amnt field to 10000. There was no matches returned until calling ObjectId('') on the given strings pulled from the database.

Node.js code:

var conditions = {}
var update = {$set: {"this.$[i].that.$[x].amnt": 1000}
var options = {arrayFilters: [{"i._id": weekId}, {"x.userId":  r.userId}]}

myModel.update(conditions, update, options, function(err, rowsAffected){
    // handler 
}

Result: { ok: 0, n: 0, nModified: 0 }

_id and userId are schema.Types.ObjectId in the schema for the model.

I tried updating the node_modules/mongodb with the latest files for 3.6.1. It appears mongoose uses 3.0.1. Printing out to console typeof(weekId) or typeof(r.userId) shows type of string. I believe this gets changed based on the schema, but either way I tried calling mongoose.Types.ObjectId(weekId) on these items to see if this resolved it, but no luck.

MongoDB: 3.6.1 Mongoose: 5.0.0-rc2

2 Answers 2

8

I don't know if Mongoose 5.0.0 is supposed to support Arrayfilters out of the box but you can achieve it by using Mongoose's command-method which directly executes on MongoDB, hence can utilize all features available which includes ArrayFilters on MongoDB 3.6.1

Example:

mongoose.connection.db.command({
  update: <YourModel>.collection.name,
  updates: [
    {
      q: { 'field1.field2._id': mongoose.Types.ObjectId(<someObjectid>) },
      u: {
        $set: { 'field1.$.field2.$[field].fieldToUpdate': "updated!" },
      },
      arrayFilters: [
        { 'field._id': mongoose.Types.ObjectId(<someObjectid>) },
      ],
    },
  ],
})
Sign up to request clarification or add additional context in comments.

Comments

7

I tried it using the mongoose v5.0.14 and it works fine with MongoDB 3.6.3 version!

This is my package.json...

"dependencies": {
  "mongoose": "^5.0.14",
}

This is my update function with arrayFilters...

...

// my id variable
let id = "5ad1f4dec48d7e156034c156";

// mongo condition
let mc = {_id: id};

// mongo dataset
let ds = {'contacts.$[i].main': false};

// mongo options
let op = {                             
  arrayFilters: [
    {
      $and: [
        {'i._id': {$ne: id}},
        {'i.type': 'mobile'},
      ],
    }],
};

<<Model>>.findOneAndUpdate(mc, ds, op, (err, doc) => {
  callback(err, doc);
});

...

3 Comments

Hi @TechWisdom, I edited my answer with a part of my code to be more specific. If do have any question, let me know.
Thanks a lot @Biruel Rick ! I also didn't include the field in the Schema, which was part of the problem.
On Mongoose ^5.0.14 findOneAndUpdate() didn't work for me. I had to use update() instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.