Search code examples
node.jsmongodbmongoosemongoose-schema

Mongoose update value in Array of Array in NodeJS


my Test Schema:

var TestSchema = new Schema({
    testName: String,
    topic: {
        topicTitle: String,
        topicQuestion: [
            {
                questionTitle: String,
                choice: [
                    {
                        name: String
                        age: Number
                    }
                ]
            }
        ]
    }
}, { collection: 'test' });
var Test = mongoose.model('test', TestSchema);

I want to update one age ($inc)value which I have the choice id.

I can have test id, topicQuestion id and choice id.

How to write this query in mongoose in NodeJS?

Normally I use the below query to update a value:

Test.findOneAndUpdate({ _id: testId }, { $inc: { ... } }, function (err, response) {
   ...
});

but it is so difficult to get in array and one more array. Thanks


Solution

  • You can use the $[] positional operator to update nested arrays.

    router.put("/tests/:testId/:topicQuestionId/:choiceId", async (req, res) => {
      const { testId, topicQuestionId, choiceId } = req.params;
    
      const result = await Test.findByIdAndUpdate(
        testId,
        {
          $inc: {
            "topic.topicQuestion.$[i].choice.$[j].age": 1
          }
        },
        {
          arrayFilters: [{ "i._id": topicQuestionId }, { "j._id": choiceId }],
          new: true
        }
      );
      res.send(result);
    });
    

    Let's say we have this existing document:

    {
        "_id" : ObjectId("5e53e7d9bf65ac4f5cbf2116"),
        "testName" : "Test 1",
        "topic" : {
            "topicTitle" : "Title",
            "topicQuestion" : [
                {
                    "_id" : ObjectId("5e53e7d9bf65ac4f5cbf211a"),
                    "questionTitle" : "Question 1 Title",
                    "choice" : [
                        {
                            "_id" : ObjectId("5e53e7d9bf65ac4f5cbf211c"),
                            "name" : "A",
                            "age" : 1
                        },
                        {
                            "_id" : ObjectId("5e53e7d9bf65ac4f5cbf211b"),
                            "name" : "B",
                            "age" : 2
                        }
                    ]
                },
                {
                    "_id" : ObjectId("5e53e7d9bf65ac4f5cbf2117"),
                    "questionTitle" : "Question 2 Title",
                    "choice" : [
                        {
                            "_id" : ObjectId("5e53e7d9bf65ac4f5cbf2119"),
                            "name" : "C",
                            "age" : 3
                        },
                        {
                            "_id" : ObjectId("5e53e7d9bf65ac4f5cbf2118"),
                            "name" : "D",
                            "age" : 4
                        }
                    ]
                }
            ]
        },
        "__v" : 0
    }
    

    If we want to increment age value of a given choice, we send a PUT request using endpoint like this http://.../tests/5e53e7d9bf65ac4f5cbf2116/5e53e7d9bf65ac4f5cbf211a/5e53e7d9bf65ac4f5cbf211b where

    "testId": "5e53e7d9bf65ac4f5cbf2116"

    "topicQuestionId": "5e53e7d9bf65ac4f5cbf211a"

    "choiceId": "5e53e7d9bf65ac4f5cbf211b"