81

私は2つのコレクションを持っています。最初のコレクションには生徒が含まれています。

{ "_id" : ObjectId("51780f796ec4051a536015cf"), "name" : "John" }
{ "_id" : ObjectId("51780f796ec4051a536015d0"), "name" : "Sam" }
{ "_id" : ObjectId("51780f796ec4051a536015d1"), "name" : "Chris" }
{ "_id" : ObjectId("51780f796ec4051a536015d2"), "name" : "Joe" }

2 番目のコレクションにはコースが含まれています。

{
        "_id" : ObjectId("51780fb5c9c41825e3e21fc4"),
        "name" : "CS 101",
        "students" : [
                ObjectId("51780f796ec4051a536015cf"),
                ObjectId("51780f796ec4051a536015d0"),
                ObjectId("51780f796ec4051a536015d2")
        ]
}
{
        "_id" : ObjectId("51780fb5c9c41825e3e21fc5"),
        "name" : "Literature",
        "students" : [
                ObjectId("51780f796ec4051a536015d0"),
                ObjectId("51780f796ec4051a536015d0"),
                ObjectId("51780f796ec4051a536015d2")
        ]
}
{
        "_id" : ObjectId("51780fb5c9c41825e3e21fc6"),
        "name" : "Physics",
        "students" : [
                ObjectId("51780f796ec4051a536015cf"),
                ObjectId("51780f796ec4051a536015d0")
        ]
}

各コース ドキュメントにはstudents、コースに登録されている学生のリストを含む配列が含まれています。学生が Web ページでコースを表示するとき、コースに登録済みかどうかを確認する必要があります。そのためにはcourses、生徒に代わってコレクションがクエリされるときに、students配列に生徒の ObjectId が既に含まれているかどうかを確認する必要があります。検索クエリの射影で指定して、配列ObjectIdから学生studentsが存在する場合にのみ取得する方法はありますか?

$elemMatch 演算子を使用できるかどうかを確認しようとしましたが、サブドキュメントの配列を対象としています。集約フレームワークを使用できることは理解していますが、この場合はやり過ぎのようです。集計フレームワークは、おそらく単一の検索クエリほど高速ではありません。返されたドキュメントがこれに似た形式になるように、コース コレクションをクエリする方法はありますか?

{
        "_id" : ObjectId("51780fb5c9c41825e3e21fc4"),
        "name" : "CS 101",
        "students" : [
                ObjectId("51780f796ec4051a536015d0"),
        ]
}
4

3 に答える 3

77

[これに基づく編集は、最近のバージョンで可能になりました]

[更新された回答] 既に登録されている場合にのみ、次の方法でクエリを実行して、クラスの名前と学生 ID を取得できます。

db.student.find({},
 {_id:0, name:1, students:{$elemMatch:{$eq:ObjectId("51780f796ec4051a536015cf")}}})

そして、あなたが期待したものが返されます:

{ "name" : "CS 101", "students" : [ ObjectId("51780f796ec4051a536015cf") ] }
{ "name" : "Literature" }
{ "name" : "Physics", "students" : [ ObjectId("51780f796ec4051a536015cf") ] }

【元の回答】今やりたいことができない。学生がオブジェクトとして配列に格納されていれば、これを行うことができるため、これは残念です。実際、特定のコースに登録している学生のリストを表示したい場合は常に学生を検索する必要があるため、ObjectId() だけを使用していることに少し驚いています(ID の最初のリストを検索してから検索します)。学生コレクションの名前をアップ - 1 つではなく 2 つのクエリ!)

(例として) コース配列に Id と名前を次のように保存する場合:

{
        "_id" : ObjectId("51780fb5c9c41825e3e21fc6"),
        "name" : "Physics",
        "students" : [
                {id: ObjectId("51780f796ec4051a536015cf"), name: "John"},
                {id: ObjectId("51780f796ec4051a536015d0"), name: "Sam"}
        ]
}

クエリは次のようになります。

db.course.find( { }, 
                { students : 
                    { $elemMatch : 
                       { id : ObjectId("51780f796ec4051a536015d0"), 
                         name : "Sam" 
                       } 
                    } 
                } 
);

その学生が CS 101 のみに登録されている場合は、次のように返されます。

{ "name" : "Literature" }
{ "name" : "Physics" }
{
    "name" : "CS 101",
    "students" : [
        {
            "id" : ObjectId("51780f796ec4051a536015cf"),
            "name" : "John"
        }
    ]
}
于 2013-04-25T04:54:02.883 に答える
24

$inオペレーターはあなたの目的をうまく果たすようです。

次のようなことができます (疑似クエリ):

if (db.courses.find({"students" : {"$in" : [studentId]}, "course" : courseId }).count() > 0) {
  // student is enrolled in class
}

または、句を削除して"course" : courseId、学生が登録されているすべてのクラスのセットを取得することもできます。

于 2013-04-24T17:31:42.003 に答える