2017-06-14 92 views
1

我有以下課程模式帶有考勤字段,該字段存儲具有以下鍵值結構(字符串:List)的字典。尤其是,出勤對象的密鑰存儲班級的日期,而值存儲出席學生的列表(學生ID)。MongoDB查詢:如何查找嵌套對象中的字符串

var CourseSchema = new Schema({ 
    attendance: {}, 
}); 

例如,單場項目可能如下:

{"_id":"559a7353186a384b54f9aea9","attendance":{"2015-12-17":["558febdb949eff4711e621e9","559020fe79f141941ddd3246"],"2015-11-14":["558febdb949eff4711e621e9","559020fe79f141941ddd3246"]} 

我試圖返回,有一個學生已經參加了課程(所以基本上返回任何課程,在其出席現場包含一個特定的學生ID,我試圖做到如下,但它返回空結果。我的查詢有什麼問題嗎?

我試着檢查這個鏈接,但它也不適用於我。 MongoDB query inside a nested array

Course.find({"attendance.$": {$in: ["558febdb949eff4711e621e9"]}}...) 
+0

這裏的問題是,你有像「2015-12-17」這樣的「命名鍵」,它阻礙了引用的解決方案的實用性。因此您的模式設計選擇是錯誤的。如果你改變了模式,那麼你可以用一種有效的方式完成你想要的東西。目前,唯一的辦法是效率不高。 –

回答

1

的解決方案是合理的,但你的模式是錯在這裏。對於像這樣的數據庫使用「命名密鑰」存在很大的問題,您應該將它們視爲「屬性」。

如在:

{ 
    "_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類型。

甚至更​​糟糕的查詢任何更復雜的,也不能告訴你哪個位置匹配。但到目前爲止最糟糕的是這些不可能使用「索引」來匹配。

因此,您真的應該考慮將數據庫模式更改爲一種將以最有效的方式支持查詢的表單。

+0

非常感謝,我會研究這個!中途改變數據庫模式是否被認爲是不好的形式? –