2016-07-02 3 views
1

サブ文書のアレイとMongoDBのドキュメントを更新する方法。以下はマングースベースのスキーマとモデルです:私はそのコレクションのモデル<em>クラス</em>、<em>学生</em>、<em>科目</em>、および[学術] <em>パフォーマンス</em>のMongoDBデータベースで働いています

var mongoose = require('mongoose'); 
var Schema = mongoose.Schema; 
var ObjectId = Schema.Types.ObjectId; 

// SUBJECT collection 
var subjectSchema = new Schema({ 
    name  : { type: String, required: true }, 
    category : { type: String, required: true } 
}); 
var Subject = mongoose.model('Subject', subjectSchema); 

// STUDENT collection 
var studentSchema = new Schema({ 
    name  : { type: String, required: true }, 
    grade  : { type: Number, required: true } 
}); 
var Student = mongoose.model('Student', studentSchema); 

// PERFORMANCE collection 
var performanceSchema = new Schema({ 
    subjectId : { type: ObjectId, ref: Subject.modelName, required: true }, 
    score  : { type: Number, required: true }, 
    maximum  : { type: Number, required: true }, 
    grade  : { type: String, required: true } 
}); 
var Performance = mongoose.model('Performance', performanceSchema); 

// *Note*: This is just to use as a sub-document schema, and not as a collection 
var classStudentSchema = new Schema({ 
    studentId : { type: ObjectId, ref: Student.modelName, required: true }, 
    performance : [performanceSchema] 
}, { _id: false }); 

// CLASS collection 
var classSchema = new Schema({ 
    name  : { type: String, required: true }, 
    scores  : [classStudentSchema] 
}); 
var Class = mongoose.model('Class', classSchema); 

classコレクションの文書はたくさんの最も複雑です。例えば、文書は次のようになります。

{ 
    "_id" : ObjectId("57758f15f68da08c254ebee1"), 
    "name" : "Grade 5 - Section A", 
    "scores" : [{ 
    "studentId" : ObjectId("5776bd36ffc8227405d364d2"), 
    "performance": [{ 
     "subjectId" : ObjectId("577694ecbf6f3a781759c54a"), 
     "score" : 86, 
     "maximum" : 100, 
     "grade" : "B+" 
    }, { 
     "subjectId" : ObjectId("5776ffe1804540e29c602a62"), 
     "score" : 74, 
     "maximum" : 100, 
     "grade" : "A-" 
    }] 
    }, { 
    "studentId" : ObjectId("5776bd36ffc8227405d364d5"), 
    "performance": [{ 
     "subjectId" : ObjectId("577694ecbf6f3a781759c54a"), 
     "score" : 94, 
     "maximum" : 100, 
     "grade" : "A" 
    }, { 
     "subjectId" : ObjectId("5776ffe1804540e29c602a62"), 
     "score" : 81, 
     "maximum" : 100, 
     "grade" : "A" 
    }] 
    }] 
} 

私は既存のクラスのドキュメントを取得することができましたし、それに学生を追加し、次のコードを使用してスコアです:

Class.findOne({ name: 'Grade 5 - Section A' }, function(err, class) { 
    if (err) throw err; 
    Student.findOne({ name: 'John Doe' }, function(err, student) { 
    if (err) throw err; 
    class.scores.push({ 
     studentId: student.id 
    }); 
    }; 
}); 

しかし、どのように私は/更新を追加する/削除しますその特定の学生のパフォーマンスですか?私は、次の方法でclassコレクションと対話できるようにする必要があります。

  • scores配列内の特定の要素を取得する)すべての学生のための、または特定の学生のためのスコアを取得/更新を追加します/ scores[n].performance配列内の特定の要素を取得し、更新の場合には(特定の対象のために、特定の生徒のスコアを削除したり、削除、追加のために、同一アレイに追加

答えて

2

これを行うには、いくつかの方法があります。私はポイントで回答します

に(

Class.findOne({ name: 'Grade 5 - Section A'}) 
    .populate('scores.studentId') 
    .exec(function(err, class) { 
     if (err) throw err; 
     //now class.scores.studentId becomes ObjectStudent 
     //hence you have all scores for all students 
}); 

追加/更新/特定の主題のために、特定の生徒のスコアを削除(スコア配列内の特定の要素を取得する)すべての学生のための、または特定の学生のためのスコアを取得します。更新または削除の場合、スコア[n] .performance配列内の特定の要素を検索します。 addの場合は、同じ配列に追加します。

Class.findOneAndUpdate({name: 'Grade 5 - Section A' 
         ,'scores.studentId': ObjectId('5776bd36ffc8227405d364d2') 
         , 'scores.performance.subjectId' : ObjectId('577694ecbf6f3a781759c54a')} 
         , {$set: {scores.performance. score: 50}} 
         , function(err, data) { 
      if (err) throw err 
    }); 

私はそれがすべての

+0

まずを助け、あなたの答えの最初の部分だけで素晴らしい仕事を願っています。私は、 'populate( 'scores.studentId')'がどのように各学生のパフォーマンスを取得するのかを正確に理解していません。非常に強力なようです。私はいくつかの質問があります:(a)1人の学生のために特定の科目の得点を取得するにはどうすればよいですか? (b)空の 'performance'配列を持つ' scores'配列に新しい学生を追加するにはどうしたらいいですか? (c)特定の生徒の1つの科目にどのようにパフォーマンスを追加するのですか? (d)と(e)は(b)と(c)と同じですが、追加するのではなく削除します。あなたは私にアップデート方法のアイデアを教えてくれました。あなたの助けを借りてありがとう! –

+1

喜んでお手伝いします。あなたが引き出すことができる最低限の文書は、クラスの最後です。特定のフィールドを取得したい場合は、それらをfind内の第2引数として渡すことができます。 findOneAndUpdate(クエリ、{'スコア。パフォーマンス。グレード:1}、関数(エラー){})。スコアを追加するには、マングースモデル、つまりmodel.scores.push({studentId:ObjectId( 'xxxxxxxxx')、performance:[}})内で 'push'演算子を使用するか、findとupdateを使用して$ push演算子を使用するか、それは原子だからです。 – Tim

+0

populateを使用して、階層全体のすべての外部キー参照を 'scores.studentId'を超えて解決できますか?これにより、studentIdリファレンスに対応する生徒を得ることができました。同様に、各生徒の 'performance'配列の' subjectId'リファレンスに対応するsubjectドキュメント全体を取得したいのですか?私の目標は、MongoDBの文脈でこの用語を使うことができるならば、完全に非正規化された 'class'文書をフェッチすることです! –

関連する問題