【问题标题】:CastError: Cast to ObjectId failed for value ...` at path "questions"CastError: Cast to ObjectId failed for value ...` at path "questions"
【发布时间】:2017-08-14 21:20:38
【问题描述】:

我目前正在使用 MongoDB / Mongoose 构建 Node 后端,我似乎在将数据绑定在一起时遇到了一些问题。具体来说,我希望所有用户都能够提交一个表单(问题表单),然后将其添加到“问题”集合中。除了被添加到问题集合之外,我还需要存储对用户直接在用户对象内回答的所有问题的引用。

您可以在下面查看我的代码。每当我向/questions 发出POST 请求时,它都会吐出这个错误。我应该注意到它成功地将文档添加到问题集合中,并且每个问题都包含创建它的用户的 ID,但主要问题是 用户的 questions 数组没有更新为包含 ID 值提交的问题。

模型/User.js

const mongoose = require('mongoose'),  
      Schema = mongoose.Schema,
      bcrypt = require('bcrypt-nodejs');


const UserSchema = new Schema({  
  email: {
    type: String,
    lowercase: true,
    unique: true,
    required: true
  },
  password: {
    type: String,
    required: true
  },
  profile: {
    firstName: { type: String },
    lastName: { type: String }
  },
  questions: [
  {
      type: Schema.Types.ObjectId,
      ref: 'Question'
  }
],
  role: {
    type: String,
    enum: ['Member', 'Client', 'Owner', 'Admin'],
    default: 'Member'
  },
  resetPasswordToken: { type: String },
  resetPasswordExpires: { type: Date }
},
{
  timestamps: true
});

/** Pre-save of user to database, 
    hash password if password is modified or new 
*/
module.exports = mongoose.model('User', UserSchema);

模型/Question.js

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

// Schema defines how questions will be stored in MongoDB
const QuestionSchema = new Schema({
  questionString: String,
  answer: Boolean,
  _createdBy : [
  {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'User'
  }
],
},{
  //user timestamps to save date created as .createdAt   
  timestamps: true
});


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

控制器/QuestionController.js

const jwt = require('jsonwebtoken'),  
      crypto = require('crypto'),
      Question = require('../models/question'),
            User = require('../models/user'),
      config = require('../config/main');


function setQuestionInfo(request) {  
  return {
    _id: request._id,
    questionString: request.questionString,
    answer: request.answer,
    user: request.user
  }
}

exports.addQuestion = function(req, res, next) {  

User.findById(req.user.id, (err, user) => {
if (err) throw new Error(err);

// We create an object containing the data from our post request
  const newQuestion = {
    questionString: req.body.questionString,
    answer: req.body.answer,
    // in the author field we add our current user id as a reference
    _createdBy: req.user._id
  };

  // we create our new post in our database
  Question.create(newQuestion, (err, question) => {
      if (err) {
        res.redirect('/');
        throw new Error(err);
      }

      // we insert our newQuestion in our posts field corresponding to the user we found in our database call
      user.questions.push(newQuestion);
      // we save our user with our new data (our new post).
      user.save((err) => {
        return res.send('sucess!');
      });
    })
  });
}

Router.js

module.exports = function(app) {
  // Initializing route groups
  const apiRoutes = express.Router(),
        userRoutes = express.Router(),
        authRoutes = express.Router(),
        questionRoutes = express.Router();

  //=========================
  // Auth Routes
  //=========================

  /** ROUTES BELOW WORK FINE -- ONLY DEALS WITH POST TO /questions
   * 


  app.use middle ware sets /auth as auth route (everything goes through /api/auth)
  apiRoutes.use('/auth', authRoutes);
  apiRoutes.get('/dashboard', requireAuth, function(req, res) {  
    res.send('It worked! User id is: ' + req.user._id + '.');
  });


  // Set user routes as a subgroup/middleware to apiRoutes
  apiRoutes.use('/user', userRoutes);

  // View user profile route
  userRoutes.get('/:userId', requireAuth, UserController.viewProfile);

  // Test protected route
  apiRoutes.get('/protected', requireAuth, (req, res) => {
    res.send({ content: 'The protected test route is functional!' });
  });
  // Registration route
  authRoutes.post('/register', AuthenticationController.register);
  // Login route
  authRoutes.post('/login', requireLogin, AuthenticationController.login);
  */

  // Problem Area --> Making POST req to /questions
  apiRoutes.post('/questions', requireAuth, QuestionController.addQuestion);

  // Set url for API group routes
  app.use('/api', apiRoutes);
};

【问题讨论】:

  • 嗨托马斯·格雷科;这是您粘贴在那里的很多代码。您可以尝试将其修改为Minimal, Complete, and Verifiable Example 吗?
  • 我很抱歉,我没有意识到我必须在模型中为每个集合添加两次,但我经历并删除了一些与我的问题无关的可靠代码。我只包括了 AuthController 和其他与身份验证相关的东西,以表明 API 工作正常(除了这个实例:P)
  • 你能用user.questions.push(question._id);代替user.questions.push(newQuestion);吗?
  • 成功了!!! @Veeram 非常感谢。你知道这个问题的原因吗?我想我需要将新的问题对象封装在newQuestion 中,然后将该对象推送到我的数据库中。再次感谢:)

标签: javascript node.js mongodb mongoose


【解决方案1】:

您已将架构定义为接受用户的问题 ID。

questions: [
  {
      type: Schema.Types.ObjectId,
      ref: 'Question'
  }

使用Question.create(newQuestion, (err, question)... 保存后,回调属性question 具有更新的数据,其中一个是ObjectId

现在您将这个 ObjectId 值添加到您从 User 模型上的 findById 获得的现有 questions 数组中。

user.questions.push(question._id);

当您在问题数组上使用 populate 时,Mongoose 将使用 questionId 填充您的问题对象,但这是检索信息的一部分。

【讨论】:

  • 太棒了。非常感谢!
猜你喜欢
  • 2017-02-06
  • 2017-03-23
  • 2022-06-14
  • 2021-04-20
  • 1970-01-01
  • 2020-12-10
  • 2013-02-03
  • 1970-01-01
相关资源
最近更新 更多