的解決方案是合理的,但你的模式是錯在這裏。對於像這樣的數據庫使用「命名密鑰」存在很大的問題,您應該將它們視爲「屬性」。
如在:
{
"_id" : ObjectId("559a7353186a384b54f9aea9"),
"attendance" : [
{
"date" : ISODate("2015-12-17T00:00:00Z"),
"student" : ObjectId("558febdb949eff4711e621e9")
},
{
"date" : ISODate("2015-12-17T00:00:00Z"),
"student" : ObjectId("559020fe79f141941ddd3246")
},
{
"date" : ISODate("2015-11-14T00:00:00Z"),
"student" : ObjectId("558febdb949eff4711e621e9")
},
{
"date" : ISODate("2015-11-14T00:00:00Z"),
"student" : ObjectId("559020fe79f141941ddd3246")
}
]
}
這將在一個模式被定義爲:
AttendanceSchmema = new Schema({
"date": Date,
"student": { "type": Schema.Types.ObjectId, "ref": "Student" }
},{ "_id": false });
CourseSchema = new Schema({
"attendance": [AttendanceSchema]
});
然後,我可以簡單地匹配給出學生:
Course.find(
{ "attendance.student": "559020fe79f141941ddd3246" },
{ "attendance.$": 1 }
)
甚至給定日期的學生:
Course.find(
{ "attendance": {
"$elemMatch": {
"student": "559020fe79f141941ddd3246",
"date": { "$gte": new Date("2015-12-15"), "$lt": new Date("2015-12-16") }
}
}},
{ "attendance.$": 1 }
)
甚至更多的可能性之間。我們把所有這些放在一個帶有「屬性」屬性的單個數組中的原因是爲了簡化查詢和存儲。
沒有這個變化,你被卡住可怕的表演查詢:當然
Course.find({ "$where": function() {
return Object.keys(this.attendance).some(function(k) {
return this.attendance[k].indexOf("558febdb949eff4711e621e9")
});
}})
假設這些值是目前「串」,因爲他們似乎是由Mixed
類型。
甚至更糟糕的查詢任何更復雜的,也不能告訴你哪個位置匹配。但到目前爲止最糟糕的是這些不可能使用「索引」來匹配。
因此,您真的應該考慮將數據庫模式更改爲一種將以最有效的方式支持查詢的表單。
這裏的問題是,你有像「2015-12-17」這樣的「命名鍵」,它阻礙了引用的解決方案的實用性。因此您的模式設計選擇是錯誤的。如果你改變了模式,那麼你可以用一種有效的方式完成你想要的東西。目前,唯一的辦法是效率不高。 –