首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >课程订阅应用程序中猫鼬模式的改进

课程订阅应用程序中猫鼬模式的改进
EN

Stack Overflow用户
提问于 2017-06-17 02:24:59
回答 2查看 1.1K关注 0票数 0

我是mongodb的新手,我正在玩一个自我项目,用户可以订阅预定义的3-4个不同的课程。每门课程每天一小时,学生可以订阅15天、30天或更长时间。

App将存储学生的信息,他们订阅了多少天和多少天的课程。

这是我的猫鼬模式。

代码语言:javascript
复制
var mongoose = require('mongoose');

var schemaOptions = {
  timestamps: true,
  toJSON: {
    virtuals: true
  }
};
var courseSchema = new mongoose.Schema({
  name: String
});
var studentSchema = new mongoose.Schema({
  name: String,
  email: { type: String, unique: true},
  phone: String,
  gender: String,
  age: String,
  city: String,
  street: String,
  picture: String,
  course: [courseSchema],
  subscriptionDays: Number,
  daysPresent: [Date]  
}, schemaOptions);

module.exports = mongoose.model('Student', studentSchema);

在这里,course是3-4门课程中的任何一门,一个学生可以同时订阅一个或多个课程.subscriptionDays是他们订阅的天数,daysPresent是他们参加这个课程的天数。

我不确定这是否是我的项目的正确模式,到目前为止我已经能够做到这一点。

与模式的混淆如下:

  • 当订阅两门不同课程的学生来到学院,但只上一门课(课程)时,我认为这个模式不支持这种情况,因为我想这样修改courseSchema, var courseSchema =新mongoose.Schema({ name: String,subsriptionDays: Number,daysPresent: Date });

但是,在这样做之后,我仍然困惑于对数据进行更改,比如每次学生参加课程时都必须将Date插入到文档中。

  • 第二个困惑是我将如何每天更新文档中的数据,只有每天必须插入的数据是天内的Date

我能从蒙古专家那里得到一些指导和建议吗?提亚

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-17 07:45:01

我认为你对扩展设计的第二个想法基本上是正确的。我只想对此进行扩展,包括对“课程”本身的“引用”,而不仅仅是嵌入在模式中的信息。

在您的用例问题中,最好用一个工作示例来解决它们:

代码语言:javascript
复制
const async = require('async'),
      mongoose = require('mongoose'),
      Schema = mongoose.Schema,
      ObjectId = Schema.Types.ObjectId;

mongoose.set('debug',true);
mongoose.connect('mongodb://localhost/school');

// Course model

const courseSchema = new Schema({
  name: String,
  info: String
});

const Course = mongoose.model('Course', courseSchema);

// Student Model

const studentCourseSchema = new Schema({
  _id: { type: ObjectId, ref: 'Course' },
  name: String,
  subscriptionDays: Number,
  daysPresent: [Date]
});

const studentSchema = new Schema({
  name: String,
  email: String,
  courses: [studentCourseSchema]
});

studentSchema.index({ "email": 1 },{ "unique": true, "background": false });

const Student = mongoose.model('Student', studentSchema);

function logOutput(content) {
  console.log( JSON.stringify( content, undefined, 2 ) )
}

async.series(
  [
    // Clear collections
    (callback) =>
      async.each(mongoose.models,
      (model,callback) => model.remove({},callback),callback),

    // Set up data
    (callback) =>
      async.parallel(
        [
          (callback) => Course.insertMany(
            [
              { "name": "Course 1", "info": "blah blah blah" },
              { "name": "Course 2", "info": "fubble rumble" }
            ],
            callback),
          (callback) => Student.insertMany(
            [
              { "name": "Bill", "email": "bill@example.com" },
              { "name": "Ted", "email": "ted@example.com" }
            ],
            callback)
        ],
        callback
      ),

    // Give bill both courses
    (callback) => {
      async.waterfall(
        [
          (callback) => Course.find().lean().exec(callback),
          (courses,callback) => {
            courses = courses.map(
              course => Object.assign(course,{ subscriptionDays: 5 }));
            let ids = courses.map( c => c._id );
            Student.findOneAndUpdate(
              { "email": "bill@example.com", "courses._id": { "$nin": ids  } },
              { "$push": {
                "courses": {
                  "$each": courses
                }
              }},
              { "new": true },
              (err, student) => {
                logOutput(student);
                callback(err);
              }
            )
          }
        ],
        callback
      )
    },

    // Attend one of bill's courses
    (callback) => Student.findOneAndUpdate(
      { "email": "bill@example.com", "courses.name": 'Course 2' },
      { "$push": { "courses.$.daysPresent": new Date() } },
      { "new": true },
      (err, student) => {
        logOutput(student);
        callback(err);
      }
    ),

    // Get Students .populate()
    (callback) => Student.find().populate('courses._id')
      .exec((err,students) => {
        logOutput(students);
        callback(err);
      }
    )
  ],
  (err) => {
    if (err) throw err;
    mongoose.disconnect();
  }
)

因此,这将为您提供一个示例,说明您询问的操作实际上是如何工作的。

  • 向学生添加了一门课程,展示了几门课程的添加,我认为您最好使用MongoDB的$push功能。为了确保您没有添加已经存在的课程,如果"query“表达式已经存在于”课程“数组中,则实际上会排除所选内容。在这个示例中,传递了一个"list“,因此我们使用$nin,但是对于单个项,您只需使用$ne: {“电子邮件”:"bill@example.com","courses._id":{ "$nin":ids } },{ "$push":{“课程”:{ "$each":课程} },
  • 添加了一个出席日期--这实际上演示了一种情况,您希望“在位置上匹配”“课程”中的项目,以便知道要更新哪一项。这是通过提供与“匹配”的条件非常类似的方法来完成的,而不是“排除”特定的数组元素。然后,在实际的“更新”部分中,我们应用相同的$push运算符,以便可以附加到"daysPresent"数组,还可以使用位置$运算符来指向与匹配条件相对应的正确的数组索引位置: {“电子邮件”:"bill@example.com","courses.name":'Course 2‘},{ "$push":{ "courses.$.daysPresent":new Date() },

另外,还有一些操作显示了在自己的集合中保留一个"Courses"列表与您可能不希望嵌入到每个学生身上的其他信息之间的关系。

示例中的最后一个操作实际上执行一个.populate(),从其他集合中实际提取此信息以供显示。

整个示例都使用mongoose.set('debug',true);进行了调试,这样您就可以看到对MongoDB的实际调用对每个操作都做了什么。

还可以了解这里使用的.findOneAndUpdate()方法,以及来自核心MongoDB文档的各种“更新操作员”

样本输出

代码语言:javascript
复制
Mongoose: courses.remove({}, {})
Mongoose: students.remove({}, {})
Mongoose: students.ensureIndex({ email: 1 }, { unique: true, background: false })
(node:10544) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
Mongoose: courses.insertMany([ { __v: 0, name: 'Course 1', info: 'blah blah blah', _id: 5944d5bc32c6ae2930174289 }, { __v: 0, name: 'Course 2', info: 'fubble rumble', _id: 5944d5bc32c6ae293017428a } ], null)
Mongoose: students.insertMany([ { __v: 0, name: 'Bill', email: 'bill@example.com', _id: 5944d5bc32c6ae293017428b, courses: [] }, { __v: 0, name: 'Ted', email: 'ted@example.com', _id: 5944d5bc32c6ae293017428c, courses: [] } ], null)
Mongoose: courses.find({}, { fields: {} })
Mongoose: students.findAndModify({ 'courses._id': { '$nin': [ ObjectId("5944d5bc32c6ae2930174289"), ObjectId("5944d5bc32c6ae293017428a") ] }, email: 'bill@example.com' }, [], { '$push': { courses: { '$each': [ { daysPresent: [], _id: ObjectId("5944d5bc32c6ae2930174289"), name: 'Course 1', subscriptionDays: 5 }, { daysPresent: [], _id: ObjectId("5944d5bc32c6ae293017428a"), name: 'Course 2', subscriptionDays: 5 } ] } } }, { new: true, upsert: false, remove: false, fields: {} })
{
  "_id": "5944d5bc32c6ae293017428b",
  "__v": 0,
  "name": "Bill",
  "email": "bill@example.com",
  "courses": [
    {
      "subscriptionDays": 5,
      "name": "Course 1",
      "_id": "5944d5bc32c6ae2930174289",
      "daysPresent": []
    },
    {
      "subscriptionDays": 5,
      "name": "Course 2",
      "_id": "5944d5bc32c6ae293017428a",
      "daysPresent": []
    }
  ]
}
Mongoose: students.findAndModify({ 'courses.name': 'Course 2', email: 'bill@example.com' }, [], { '$push': { 'courses.$.daysPresent': new Date("Sat, 17 Jun 2017 07:09:48 GMT") } }, { new: true, upsert: false, remove: false, fields: {} })
{
  "_id": "5944d5bc32c6ae293017428b",
  "__v": 0,
  "name": "Bill",
  "email": "bill@example.com",
  "courses": [
    {
      "subscriptionDays": 5,
      "name": "Course 1",
      "_id": "5944d5bc32c6ae2930174289",
      "daysPresent": []
    },
    {
      "subscriptionDays": 5,
      "name": "Course 2",
      "_id": "5944d5bc32c6ae293017428a",
      "daysPresent": [
        "2017-06-17T07:09:48.662Z"
      ]
    }
  ]
}
Mongoose: students.find({}, { fields: {} })
Mongoose: courses.find({ _id: { '$in': [ ObjectId("5944d5bc32c6ae2930174289"), ObjectId("5944d5bc32c6ae293017428a") ] } }, { fields: {} })
[
  {
    "_id": "5944d5bc32c6ae293017428b",
    "__v": 0,
    "name": "Bill",
    "email": "bill@example.com",
    "courses": [
      {
        "subscriptionDays": 5,
        "name": "Course 1",
        "_id": {
          "_id": "5944d5bc32c6ae2930174289",
          "__v": 0,
          "name": "Course 1",
          "info": "blah blah blah"
        },
        "daysPresent": []
      },
      {
        "subscriptionDays": 5,
        "name": "Course 2",
        "_id": {
          "_id": "5944d5bc32c6ae293017428a",
          "__v": 0,
          "name": "Course 2",
          "info": "fubble rumble"
        },
        "daysPresent": [
          "2017-06-17T07:09:48.662Z"
        ]
      }
    ]
  },
  {
    "_id": "5944d5bc32c6ae293017428c",
    "__v": 0,
    "name": "Ted",
    "email": "ted@example.com",
    "courses": []
  }
]
票数 1
EN

Stack Overflow用户

发布于 2017-06-17 04:29:34

架构,您可以定义如下:

代码语言:javascript
复制
var mongoose = require('mongoose');
var courseSchema = new mongoose.Schema({
  name: String
});

var studentSchema = new mongoose.Schema({
  name: String,
  email: { type: String, unique: true},
  phone: String,
  gender: String,
  age: String,
  city: String,
  street: String,
  picture: String,
  courses: [{
             course:{type:mongoose.Schema.Types.ObjectId,ref:'courseSchema'},
             isAttending:{type:Boolean ,default:false}
                   }],
  subscriptionDays: Number,
  daysPresent: [Date]
}, schemaOptions);

module.exports = mongoose.model('Student', studentSchema);

isAttending将解决您的问题,如果学生订阅3门课程,并去特定的一门课程,那么isAttending将是正确的,否则错误。

  • 您可以使用克隆 npm模块,它将在您设定的时间上运行一个函数,并使您的生活变得轻松。

谢谢

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44600205

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档