2

I am using MongoDB, Mongoose, Node.js and Express.js on a site. I have researched Tutorials Point, the MongoDB docs, Stack Overflow, and Mongoosejs.com, but can't find the answer to this question. I have this as one of my document models:

const mongoose = require('mongoose')
const Schema = mongoose.Schema;

const QuestionSchema = new Schema ({
    userid: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'User',
        required: false
    },
    title: String,
    keyword1: String,
    keyword2: String,
    keyword3: String,
    body: String,
    upvotes: {
        type: Number,
        default: 0
    },
    datePosted: {
        type: Date,
        default: new Date()
    },
    answers: [{
        respondentID: mongoose.Schema.Types.ObjectId,
        respondent: String,
        text: String,
        date: Date,
        upvotes: Number
    }]
});

const Question = mongoose.model('Question', QuestionSchema);

module.exports = Question

On one of the pages, I want to display all of the "answers" which is an array of subdocuments embedded within the "Questions" model you see above. Here is my express.js controller that seeks to "extract" the answers array (the console.log entries are me attempting different approaches to get the answers array):

const { typeOf } = require('mathjs');
const Question = require('../models/Question')

module.exports = async (req,res) =>{
    console.log("You are inside displayAnswers controller!")
    const thisQuestionID = req.body.questionID;
    console.log("Display answers ID: " + thisQuestionID);
    
    if (thisQuestionID == 0) {
        console.log("Inside thisQuestionID == 0")
        res.redirect("index");
    } else {    
        const answers = await Question.find({"_id" : thisQuestionID}, {"answers": 2});   
        console.log("Answers: " + answers)
        console.log("Answer[0]: " + answers.answers[0])
        console.log(typeOf(answers.answers[0]))
        console.log("Answers Length: " + answers[0].length)
        console.log("Answers Size: " + answers[0].size)
        res.render('displayAnswers', {
            thisQuestionID,
            answers
        })
    }
}

The problem I have is that the answers variable shows up like this in the console: enter image description here

But I cannot seem to access the subdocuments. I thought I could say answers[0] or answers[#], where # is 1, or 2 or whatever the index of the subdoc is, etc but anything other than answers[0] is undefined and answers.length always shows up as "1". I can't seem to find the syntax that allows me to iterate over each individual document within the array of subdocuments. I also checked console.log(typeOf(answers)) and it confirmed that it is an array, so I am lost as to why I can't access each subdoc in the array by saying answers[0] and answers1, etc. It is as if Mongoose/Javascript thinks that answers is an array of length 1 and that there is only one element inside of it even though there are two subdocs in there separated by commas.

Any thoughts?

2
  • Your variable answers is the whole object, so you must say answers.answers[0]. Commented Jul 10, 2022 at 13:03
  • I just tried that and it shows up as undefined. Here is the error -console.log("Answers.answers[0]: " + answers.answers[0]) ^ TypeError: Cannot read properties of undefined (reading '0') Commented Jul 10, 2022 at 13:05

1 Answer 1

1

I think you're just getting confused what is the return type, possibly because of bad naming:

const answers = await Question.find({{"_id" : thisQuestionID})

This syntax returns an array of "Questions", just because you project only specific sub fields ("answers" in this case) does not change that.

This means answers looks like this:

[
  { answers: Answer[] }
]

You should either do: ( instead of find we use findOne to simply the code )

const questionBody = await Question.findOne({"_id" : thisQuestionID}, {"answers": 2});
const answers = questionBody.answers

Or even cleaner is to just use distinct

const answers = await Question.distinct("answers", {"_id" : thisQuestionID});

Both will give you an array of answers as you expect.

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

Comments

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.