如何改进这种数据模型,模式和关系

时间:2015-07-26 07:16:48

标签: mongodb meteor meteor-accounts meteor-autoform meteor-helper

我使用了meteor,mongoDB和auto-form。我的数据模型中有很多实体。 学院有一些学生,老师和班级。班级有一些学生和一名教师,每个学生都有一些成绩。

我设计了这个架构:

Schema = {};
Schema.UserProfile = new SimpleSchema({
    name: {
        type: String,
        label: "Name"
    },
    family: {
        type: String,
        label: "Family"
    },
    address: {
        type: String,
        label: "Address",
        optional: true,
        max: 1000
    },
    workAddress: {
        type: String,
        label: "WorkAddress",
        optional: true,
        max: 1000
    },
    phoneNumber: {
        type: Number,
        label: "Phone Number",
        optional: true
    },
    mobileNumber: {
        type: Number,
        label: "Phone Number"
    },
    birthday: {
        type: Date,
        optional: true
    },
    gender: {
        type: String,
        allowedValues: ['Male', 'Female'],
        optional: true
    },
    description: {
        type: String,
        label: "Description",
        optional: true,
        max: 1000
    }

});
Schema.User = new SimpleSchema({
    username: {
        type: String,
        regEx: /^[a-z0-9A-Z_]{3,15}$/
    },
    emails: {
        type: [Object],
        // this must be optional if you also use other login services like facebook,
        // but if you use only accounts-password, then it can be required
        optional: true
    },
    "emails.$.address": {
        type: String,
        regEx: SimpleSchema.RegEx.Email
    },
    "emails.$.verified": {
        type: Boolean
    },
    createdAt: {
        type: Date,
        optional: true
    },
    profile: {
        type: Schema.UserProfile,
        optional: true
    },
//    // Add `roles` to your schema if you use the meteor-roles package.
//    // Option 1: Object type
//    // If you specify that type as Object, you must also specify the
//    // `Roles.GLOBAL_GROUP` group whenever you add a user to a role.
//    // Example:
//    // Roles.addUsersToRoles(userId, ["admin"], Roles.GLOBAL_GROUP);
//    // You can't mix and match adding with and without a group since
//    // you will fail validation in some cases.
//    roles: {
//        type: Object,
//        optional: true,
//        blackbox: true
//    }
//    // Option 2: [String] type
//    // If you are sure you will never need to use role groups, then
//    // you can specify [String] as the type
    roles: {
        type: [String],
        optional: true
    }
});
//Meteor.users.attachSchema(Schema.User);

Schema.Grade: {
    student: Schema.User,
class: Schema.Class,
    gradeValue: value
}

Schema.Class: {
    teacher: Schema.User,
    students: {
        type: [Schema.User]
    },
    grades: {
        type: [Schema.Grade]
    }
}

Schema.Academy: {
    name: {
        label: "academy name",
        type: String
    },
    students: {
        type: [Schema.User]
    },
    teachers: {
        type: [Schema.User]
    },
    classes: {
        type: [Schema.Class]
    }
}

但我认为这不是最好的,而且会遇到很多重复。

我需要以下查询:

academy classes
academy students
academy teachers
students classes
students grades
student profile
class students
class teacher
class grades
teacher students
teacher classes
teacher profile

1 个答案:

答案 0 :(得分:1)

首先要识别实体:student, teacher, class, academy

其次,确定从最大的关系开始的关系:

  • 1个学院有很多课程(1:M)
  • 1班有很多学生,1名学生有很多班(M:N)
  • 1名教师有很多班级(1:M)< - 没有教师助理,联合讲座等。

接下来是关系模式。这里的技巧是最小化数组的使用,因此对于每个1:M的关系,将外键放在M:

  • 学院:_id, name
  • class:_id, name, teacherId, academyId
  • 老师:“个人资料”
  • 学生:“个人资料”

所有外键的索引(teacherId,academyId)。

现在我们没有任何重复,但我们仍然需要处理学生:班级关系。

Grades集合的示例是教科书3NF,SQL方式。它没有错,这是一个很好的解决方案。 (只需确保在外键上编制索引!)。

或者,在学生文档上你可以有一个对象,每个字段都是classId&每个值都是等级。

另一个选择是在类文档上有一个学生对象,每个字段都是studentId,每个值都是等级。

您如何确定最佳选择是访问模式。如果你有一个学生门户网站,他们可以看到他们的课程和成绩,将它放在学生集合上是更有意义的,偶尔的查询得到一个平均课程将更加昂贵,因为它必须遍历所有学生。对于在类集合中嵌套,反之亦然。