【问题标题】:How could I reference a model to my User model with Express/Mongoose如何使用 Express/Mongoose 将模型引用到我的用户模型
【发布时间】:2018-11-09 17:20:37
【问题描述】:

我有两个模型,一个是我的用户模型,另一个是我的课程模型。我想拥有它,因此当用户(教师)创建课程时,它将该课程分配给他们,反之亦然。以下是我的模型以便更好地解释:

课程架构/模型:

var CourseSchema = new Schema({
    courseID: {
        type: Number,
        unique: true
    },
    courseName: String,
    courseDesc: {
        type: String,
        default: "No course description provided."
    },
    coursePicture: {
        type: String,
        required: false
    },
    teacher: [
        {
           type: mongoose.Schema.Types.ObjectId,
           ref: 'User'
        }
    ],
    students: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Student'
         }
    ]
})

用户架构/模型:

var UserSchema = new mongoose.Schema({  
  firstName: String,
  lastName: String,
  email: String,
  courses: [
    {
       type: mongoose.Schema.Types.ObjectId,
       ref: 'Course'
    }
  ], 
  password: String
});

基本上,我想在我的前端使用它,我可以执行 course.teacher.firstName 或 user.courses 之类的操作。我的模式在两个不同的文件中,但我相信这很好。这就像在用户创建帖子时为其分配帖子一样。我不知道我怎么能做到这一点,因为我已经尝试了很多事情。

现在,我目前有这个用于创建课程。

// Creates a new course
router.post('/create', function (req, res) {
    Course.create({
            courseID : req.body.courseID,
            courseName : req.body.courseName,
            courseDesc : req.body.courseDesc,
            coursePicture : req.body.coursePicture,
            teacher : req.body.id,
            students: req.body.students
        }, 
        function (err, course) {
            if (err) return res.status(500).send("There was a problem adding the information to the database.");
            res.status(200).send(course);

        });
});

我已经在该代码 ^ 所属的控制器中引用了 User 模型,因此 var User = require('../user/User'); 我相信这是实现这一目标所必需的。如果您有任何问题,请告诉我,因为我不擅长解释此类问题。

希望有人能帮帮我!

谢谢。

【问题讨论】:

  • 那是什么问题?
  • 对不起,我应该改写一下。我没有问题,我只是不知道如何将课程链接到用户(教师)并将用户(教师)链接到课程,因此我可以使用帖子中提到的字段: course.teacher .firstName 或 user.courses
  • 这是个好问题。我在下面的回答中提供了一个全面的答案以及一些数据库设计技巧。

标签: javascript node.js rest express mongoose


【解决方案1】:

这是数据库设计的问题。应该只有一个地方存储有关课程的信息,即 Courses 表和 Users 表应该对课程一无所知。应该有一个表将课程与用户相关联:UserCourseRelations 表。

我会强烈避免在用户表中存储与用户相关的 courseId 数组的方法,因为这是不必要的耦合,因此不是好的数据库设计。此外,随着这些数组在每一行上的增长,它会阻碍对用户表的读取。

以下是我的处理方法。请注意,其中一些代码使用 ES6 语法。以下代码未经测试,但应该可以工作。看看:

创建 CourseSchema 和 CourseModel

var CourseSchema = new mongoose.Schema({
    courseID: {
        type: Number,
        unique: true
    },
    courseName: String,
    courseDesc: {
        type: String,
        default: "No course description provided."
    },
    teacherId: {
        type: mongoose.Schema.Types.ObjectId,
    }
    coursePicture: {
        type: String,
        required: false
    },
    students: [
        {
            type: mongoose.Schema.Types.ObjectId,
            ref: 'Student'
        }
    ]
})

CourseSchema.statics.createNew = function(data, callback) {
    // do some verification here

    // insert the new course
    return new this(data).save((err, dbCourse) => {
        if (err) {
            return callback(err)
        }

        UserCourseRelationSchema.insertNew('teacher', userId, courseID, (err, dbUserCourseRelation) => {
            if (err) {
                return callback(err)
            }

            // done. return the new course
            callback(null, dbCourse)
        })
    })

    CourseSchema.statics.getByIds = function(courseIDs, callback) {
        // find all of the courses where the courseID is in the courseIDs array
        // see https://docs.mongodb.com/manual/reference/operator/query/in/
        this.find({courseID: {$in: courseIDs}}, (err, courses) => {
            if (err) {
                // something went wrong
                return callback(err)
            }
            callback(null, courses)
        })
    }
}

let CourseModel mongoose.model('courses', CourseSchema);

创建将课程与用户相关联的 UserCourseRelationSchema 和 UserCourseRelationModel,反之亦然

var UserCourseRelationSchema = new mongoose.Schema({  
    userId: {
        type: String,
        required: true,
    },
    courseID: {
        type: Number,
        required: true,
    },
    type: {
        type: String,
        enum: ['teacher', 'student'],
        required: true,
    },
});

UserCourseRelationSchema.statics.createNew = function(type, courseID, userId, callback) {
    // do some verification here. I suggest making sure this relation doesn't already exist

    // insert the new course
    return new this({
        courseID: courseID,
        userId: userId,
        type: type,
    }).save((err, dbUserCourseRelation) => {
        if (err) {
            return callback(err)
        }

        // return the new relation
        callback(null, dbRelation)
    })
}

UserCourseRelationSchema.statics.getTeacherRelationCourseIdsByUserId = function(userId, callback) {
    let query = this.find({userId: userId, type: 'teacher'})
    query.distinct('courseID') // get an array of only the distinct courseIDs
    query.exec((err, courseIDs) => {
        if (err) {
            // something went wrong
            return callback(err)
        }
        callback(null, courseIDs)
    })
}

let UserCourseRelationModel = mongoose.model('user_course_relations', UserCourseRelationSchema);

创建 UserSchema 和 UserModel

var UserSchema = new mongoose.Schema({  
    firstName: String,
    lastName: String,
    email: String,
    password: String
});

UserSchema.statics.getAllCoursesById = function(userId, callback) {
    // get the relations for the courses the user is a teacher of
    UserCourseRelationModel.getTeacherRelationCourseIdsByUserId(userId, (err, courseIDs) => {
        // get the courses by the returned coursIDs
        CourseModel.getByIds(courseIDs, (err, courses) => {
            if (err) {
                // something went wrong
                return callback(err)
            }
            callback(nul, courses)
        })
    })
}

let UserModel = mongoose.model('users', UserSchema);

// -- create the router

// Creates a new course
router.post('/create', function (req, res) {
    CourseModel.createNew({
        courseID : req.body.courseID,
        courseName : req.body.courseName,
        courseDesc : req.body.courseDesc,
        coursePicture : req.body.coursePicture,
        teacher : req.body.id,
        students: req.body.students
    }, function (err, course) {
        if (err) return res.status(500).send("There was a problem adding the information to the database.");
        res.status(200).send(course);
    });
});

 // -- done

我还建议尽可能使用 Promise,因为它使所有这些逻辑变得更加简单。

【讨论】:

  • mongodb是noSql数据库,没有关系,有子文档
  • 你好!感谢您的回复。我不熟悉 ES6 语法,实际上是整个 Node/Express/Mongoose 的初学者。这些更改对于实现我想要做的事情真的有必要吗?我正在查看link,我觉得所有这些更改都不是真正需要的。不过我不是专家,只是很难理解你做了什么。
  • @MedetTleukabiluly “关系”不是 sql 保留的概念。关系是您可以随心所欲实施的东西。我在回答中展示的是一种实现关系的方法。这是数据库设计的问题,而不是技术问题。正如我所说,如果你走上重耦合表的道路,查询将变得越来越昂贵。
  • @omar 这些更改不是必需的,但如果您不想在不久的将来将头撞到墙上,我强烈建议您进行这些更改。这里唯一的新语法是箭头函数 () => 和解构赋值。您的服务器应该有 ES6,但如果它没有让我知道,我可以为您调整答案中的语法。
  • @lwdthe1 我将不胜感激。您是否有 Discord 或其他问题,以便我们可以聊天,以便我可以与您进行更多讨论,因为我对此仍有一些问题
【解决方案2】:
// Creates a new course
router.post('/create', function (req, res) {
    Course.create({
            courseID : req.body.courseID,
            courseName : req.body.courseName,
            courseDesc : req.body.courseDesc,
            coursePicture : req.body.coursePicture,
            teacher : req.body.id, // find this user
            students: req.body.students,
            attendance: req.body.attendance 
        }, 
        function (err, course) {
            User.findById(req.body.id, function(err, user) {
                user.update({
                    $push: {
                        courses: course._id
                    }
                }, function(err) {
                     if (err) return res.status(500).send("There was a problem adding the information to the database.");
                     res.status(200).send(course);
                })
            })
        });
});

【讨论】:

  • 我试过了,它确实有效,但不是我想做的,因为我想引用 user.courses.courseName 之类的东西。这只会放置 ID,我认为让它发送整个课程对象并不是最好的主意。
猜你喜欢
  • 1970-01-01
  • 2011-06-28
  • 2018-08-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-15
  • 2015-03-29
  • 2013-09-01
相关资源
最近更新 更多