0
votes

I am working on basic Stack Overflow clone using Node Js and MongoDB. When I was testing upvote I fall in error TypeError: Cannot read property 'upvotes' of null. I tried everything on the internet but didn't get anything working. I am getting an error for the code below

if (question.upvotes.filter(upvote => upvote.user.toString() === req.user.id.toString()).length > 0)

You can see the above syntax in API Code for upvote route.

This is my model for upvotes:

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

const QuestionSchema = new Schema({
  user: {
    type: Schema.Types.ObjectId,
    ref: "myPerson"
  },
  textone: {
    type: String,
    required: true
  },
  texttwo: {
    type: String,
    required: true
  },
  name: {
    type: String
  },
  upvotes: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: "myPerson"
      }
    }
  ],
  answers: [
    {
      user: {
        type: Schema.Types.ObjectId,
        ref: "myPerson"
      },
      text: {
        type: String,
        required: true
      },
      name: {
        type: String
      },
      date: {
        type: Date,
        default: Date.now
      }
    }
  ],
  date: {
    type: Date,
    default: Date.now
  }
});

module.exports = Question = mongoose.model("myQuestion", QuestionSchema);

Below i have pasted my API for upvote

const express = require("express");
const router = express.Router();
const mongoose = require("mongoose");
const passport = require("passport");
const jwt = require("../../strategies/jsonwtStrategy")(passport);

//Load person model
const Person = require("../../models/Person");

//Load profile model
const Profile = require("../../models/Profile");

//Load Question model
const Question = require("../../models/Question");

//@type  GET
//@route    /api/questions
// @desc    route for getting  questions
// @access  PUBLIC
router.get("/", (req, res) => {
  Question.find()
    .sort("-date")
    .then(questions => res.json(questions))
    .catch(err => res.json({ noquestions: "No questions to display" }));
});

//@type  POST
//@route    /api/questions/
// @desc    route for submitting question
// @access  PRIVATE

router.post(
  "/",
  passport.authenticate("jwt", { session: false }),
  (req, res) => {
    const newQuestion = new Question({
      textone: req.body.textone,
      texttwo: req.body.texttwo,
      user: req.user.id,
      name: req.body.name
    });
    newQuestion
      .save()
      .then(question => res.json(question))
      .catch(err => console.log("unable to post question" + err));
  }
);

//@type  POST
//@route    /api/questions/answers/:id
// @desc    route for submitting answers to questions
// @access  PRIVATE
router.post(
  "/answers/:id",
  passport.authenticate("jwt", { session: false }),
  (req, res) => {
    Question.findById(req.params.id)
      .then(question => {
        const newAnswer = {
          user: req.body.id,
          name: req.body.name,
          text: req.body.text
        };
        question.answers.unshift(newAnswer);
        question
          .save()
          .then(question => res.json(question))
          .catch(err => console.log(err));
      })
      .catch(err => console.log(err));
  }
);

//@type  POST
//@route    /api/questions/upvote/:_id
// @desc    route for upvoting
// @access  PRIVATE
router.post(
  "/upvote/:id",
  passport.authenticate("jwt", { session: false }),
  (req, res) => {
    Profile.findOne({ user: req.user.id })
      .then(profile => {
        Question.findById(req.params.id)
          .then(question => {
            if (
              question.upvotes.filter(
                upvote => upvote.user.toString() === req.user.id.toString()
              ).length > 0
            ) {
              return res.status(400).json({ noupvote: "User already upvoted" });
            }
            question.upvotes.unshift({ user: req.user.id });
            question
              .save()
              .then(question => res.json(question))
              .catch(err => console.log(err));
          })
          .catch(err => console.log(err));
      })
      .catch(err => console.log(err));
  }
);

module.exports = router;

Error i'm getting..

TypeError: Cannot read property 'upvotes' of null at C:\Users\Subhash Chaudhary\Desktop\NodeJsLearning\09bigstack\routes\api\questions.js:87:24 at processTicksAndRejections (internal/process/task_queues.js:93:5)

2
Looks like Question.findById(req.params.id) isn't returning anythinghalf of a glazier
ohh, Thanks. Actually the course which I enrolled had MLab used and i was using MongoDB Atlas. In Mlab it is req.params.id and in Mongodb atlas it is req.params._id. I was messed there. Thanks, it worked.Subhash Chaudhary

2 Answers

0
votes

it happened because in the tutorial instructor was using MLab which returns id and I was using MongoDB which returns _id. Question.findById(req.params.id) returned nothing then i changed it to Question.findById(req.params._id) and it worked. The suggestion i got in comment.

0
votes

you can do this using mongoose schema like ;

var mongoose = require('mongoose');
var id = mongoose.Types.ObjectId(req.params.id);
Question.findById(id);

here, we convert the id in to the '_id' or we can say that 'ObjectId' of mongoose which is the schema type object id.