2017-06-14 20 views
1

出席者フィールドを持つ次のコーススキーマがあります。出席者フィールドには、次のキー値構造(文字列:リスト)の辞書が格納されています。特に、出席オブジェクトのキーにはクラスの日付が格納され、値には出席した学生のリスト(学生ID)が格納されます。例えばMongoDBクエリ:ネストされたオブジェクト内の文字列を見つける方法

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

次のように、単一コースの項目は次のようになります。

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

を私は基本的にその出席者フィールドのすべてのコースを返す(学生参加していたコースを返すようにしようとしています

私はこのリンクをチェックしようとしましたが、それは私のためにも機能しません。 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") 
      } 
    ] 
} 

Course.find(
    { "attendance.student": "559020fe79f141941ddd3246" }, 
    { "attendance.$": 1 } 
) 

あるいは:

AttendanceSchmema = new Schema({ 
    "date": Date, 
    "student": { "type": Schema.Types.ObjectId, "ref": "Student" } 
},{ "_id": false }); 

CourseSchema = new Schema({ 
    "attendance": [AttendanceSchema] 
}); 

それから私は、単に与えられたとして、学生のために一致させることができます所与の日付の学生:

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

ありがとう、私はこれを調べます!途中でデータベーススキーマを変更するだけの悪いフォームとは考えられますか? –

関連する問題