将两个参考阵列排在一起

时间:2017-05-13 16:03:29

标签: mongodb database-design mongoose

假设我有以下架构:

var QuizSchema = new mongoose.Schema({
    name: { type: String, required: true },
    questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }],
    questionGroups: [{ type: mongoose.Schema.Types.ObjectId, ref: 'QuestionGroup' }]
});

var QuestionSchema = new mongoose.Schema({
    number: { type: String, required: true }, // e.g. 1, a, i, anything
    question: { type: String, required: true },
    type: { type: String, enum: ['multiple choice', 'multiple select', 'short answer'] },
    choices: [String],
    answers: [String]
});

var QuestionGroupSchema = new mongoose.Schema({
    number: { type: String, required: true }, // e.g. 1, a, i, anything
    prompt: { type: String },
    questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }]
});

我正在尝试设计一种允许我一起订购问题和问题组的方式

我在考虑添加一个新字段order

var QuizSchema = new mongoose.Schema({
    // ...
    order: [
        {
            type: { type: String, enum: ['Question', 'QuestionGroup'] },
            id: mongoose.Schema.Types.ObjectId // reference
        }
    ]
});

这样在数据库中,该字段将包含诸如

之类的内容
[
     { type: 'Question', id: ObjectId('57867a34567g67790') },
     { type: 'Question', id: ObjectId('57867a34567g67765') },
     { type: 'QuestionGroup', id: ObjectId('69864b64765y45645') },
     { type: 'Question', id: ObjectId('57867a34567g67770') },
     { type: 'QuestionGroup', id: ObjectId('69864b64767y45647') }
]

这可能意味着我需要将有序的问题和问题组列表“填充”为

quiz.populate('questions questionGroups').exec(function (err, quiz) {
    // sort questions and groups by the order
    quiz.order = quiz.order.map(function (o) {
        if (o.type === 'QuestionGroup') {
            return quiz.questionGroups.id(o.id);
        }
        return quiz.questions.id(o.id);
    });
});

所以我的问题是:有没有更好的方法来设计它?

1 个答案:

答案 0 :(得分:2)

Virtuals可以派上用场;没有在db中持久化order字段并且每次都在客户端上进行计算:

var QuizSchema = new mongoose.Schema({
    name: { type: String, required: true },
    questions: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Question' }],
    questionGroups: [{ type: mongoose.Schema.Types.ObjectId, ref: 'QuestionGroup' }]
},
{
    toObject: {
        virtuals: true
    },
    toJSON: {
        virtuals: true 
    }
}
);

QuizSchema
.virtual('order')
.get(function() {
    return this.questions.concat(this.questionGroups); //questions followed by questionGroups
});

排序createdAt当然是可选的,但为此您需要在问题和问题组中包含此字段:

Quiz.find({}, function (err, quiz) {
    //...
})
.populate({path : 'questions', options: {sort: { 'createdAt': 1 }}})
.populate({path : 'questionGroups', options: {sort: { 'createdAt': 1 }}});