9

私はmongodbに次の文書を持っています

    {
        "_id" : ObjectId("517b88decd483543a8bdd95b"),
        "studentId" : 23,
        "students" : [
          {
           "id" : 23,
           "class" : "a"
           },
          {
           "id" : 55,
           "class" : "b"
           }
        ]
     }
     {
        "_id" : ObjectId("517b9d05254e385a07fc4e71"),
        "studentId" : 55,
        "students" : [
           {
            "id" : 33,
            "class" : "c"
          }
         ]
     }

Note:実際のデータではありませんが、スキーマはまったく同じです。

Requirement:単一のクエリを使用して、学生配列内のstudentIdand (idに一致するドキュメントを検索します。students.id

以下のようなコードを試しました

db.data.aggregate({$match:{"students.id":"$studentId"}},{$group:{_id:"$student"}});

Result:空の配列。{"students.id":"$studentId"} を {"students.id":33} に置き換えると、上記の json の 2 番目のドキュメントが返されます。

単一のクエリを使用して、このシナリオのドキュメントを取得することは可能ですか?

4

3 に答える 3

13

可能であれば、データを保存する際に条件を設定して、真偽をすばやく確認できるようにすることをお勧めします ( isInStudentsList)。そのタイプのクエリを実行すると、非常に高速になります。

それ以外の場合は、Aggregation フレームワーク パイプラインを使用して、1 つのクエリで必要なことを行う比較的複雑な方法があります。

db.students.aggregate( 
    {$project: 
        {studentId: 1, studentIdComp: "$students.id"}},  
    {$unwind: "$studentIdComp"}, 
    {$project : { studentId : 1, 
        isStudentEqual: { $eq : [ "$studentId", "$studentIdComp" ] }}}, 
    {$match: {isStudentEqual: true}})

入力例を考えると、出力は次のようになります。

{
    "result" : [
         {
             "_id" : ObjectId("517b88decd483543a8bdd95b"),
             "studentId" : 23,
             "isStudentEqual" : true
         }
    ],
    "ok" : 1
}

手順の簡単な説明:

  1. juststudentIdを使用してドキュメントのプロジェクションを作成し、 のみを含む配列を使用して新しいフィールドをid作成します (したがって、最初のドキュメントには[23, 55].
  2. その構造を使用して、$unwind . これにより、配列内の配列要素ごとに新しい一時ドキュメントが作成されますstudentIdComp
  3. 次に、これらのドキュメントを取得して、新しいドキュメント プロジェクションを作成します。これは、 とという 2 つのフィールドの等価性を比較するstudentIdと という名前の新しいフィールドを引き続き持ちます。この時点で、これら 2 つのフィールドを含む単一の一時ドキュメントがあることに注意してください。isStudentEqualstudentIdstudentIdComp
  4. 最後に、比較値isStudentEqualが true であることを確認し、それらのドキュメントを返します (元のドキュメント_idstudentId.
  5. 学生がリストに複数回含まれていた場合は、結果をグループ化するstudentId_id、重複を防ぐ必要があるかもしれません (しかし、それが必要かどうかはわかりません)。
于 2013-04-27T13:43:22.437 に答える
0

残念ながら無理です(;_;)

この問題を解決するには、 $whereステートメントを使用する必要があります(例: Finding embedded document in mongodb? )。

ただし、$whereは集計フレームワークでの使用が制限されています

于 2013-04-27T10:51:01.793 に答える
-1

db.data.find({students: {$elemMatch: {id: 23}} , studentId: 23});

于 2013-04-27T10:48:37.380 に答える