0

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

2 Answers 2

1

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"

Sign up to request clarification or add additional context in comments.

Comments

0

You need to inform what choice you want and, on the update section, you need change the way you do increment.

Example:

Test.findOneAndUpdate({ _id: testId, topicQuestion.choice._id: choiceId}, { 'topicQuestion.$.choice': {$inc: { age: <numberToIncrement> }}}, {new: true}, function (err, response) {
   ...
});

3 Comments

Thanks for reply, but I got null for the response and the age has no update. Test.findOneAndUpdate({ _id: testId, 'topicQuestion.choice._id': choiceId}, { 'topicQuestion.$.choice': {$inc: { age: 1 }}}, {new: true}, function (err, response) {
Did you pass the choiceId like pass the testId?
Can try in this way too: [...]{ $inc: {'topicQuestion.$.choice.$.age': 1}}, {new:true}[...]

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.