web-dev-qa-db-ja.com

$ elemMatch(射影)が基準に一致するすべてのオブジェクトを返すようにします

ここ の例を使用します

{
 _id: 1,
 zipcode: 63109,
 students: [
              { name: "john", school: 102, age: 10 },
              { name: "jess", school: 102, age: 11 },
              { name: "jeff", school: 108, age: 15 }
           ]
}
{
 _id: 2,
 zipcode: 63110,
 students: [
              { name: "ajax", school: 100, age: 7 },
              { name: "achilles", school: 100, age: 8 },
           ]
}

{
 _id: 3,
 zipcode: 63109,
 students: [
              { name: "ajax", school: 100, age: 7 },
              { name: "achilles", school: 100, age: 8 },
           ]
}

{
 _id: 4,
 zipcode: 63109,
 students: [
              { name: "barney", school: 102, age: 7 },
           ]
}

走ったら

db.schools.find( { zipcode: 63109 },
             { students: { $elemMatch: { school: 102 } } } )

各配列のfirstの結果が得られます。これに名前を付ける:

{ "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] }
{ "_id" : 3 }
{ "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }

条件に一致する配列のすべてのオブジェクト(最初のオブジェクトだけでなく)を返すようにするにはどうすればよいですか?これを意味する:

{
 _id: 1,
 students: [
              { name: "john", school: 102, age: 10 },
              { name: "jess", school: 102, age: 11 }
           ]
}    
{ _id: 3 }
{_id: 4, students: [ { name: "barney", school: 102, age: 7 }]}
22
Diolor

複数のサブドキュメントを返すには、集約フレームワークを使用する必要があります。これにより、探しているすべてのサブドキュメントが返されます。

db.Zip.aggregate(
  {$match: {zipcode: 63109}},
  {$unwind: "$students"},
  {$match: {"students.school": 102}}
)

さまざまなことを実行してさまざまな出力を取得できますが、これは次のようになります。

{
    "result" : [
        {
            "_id" : 1,
            "zipcode" : 63109,
            "students" : {
                "name" : "john",
                "school" : 102,
                "age" : 10
            }
        },
        {
            "_id" : 1,
            "zipcode" : 63109,
            "students" : {
                "name" : "jess",
                "school" : 102,
                "age" : 11
            }
        },
        {
            "_id" : 4,
            "zipcode" : 63109,
            "students" : {
                "name" : "barney",
                "school" : 102,
                "age" : 7
            }
        }
    ],
    "ok" : 1
}
20
EmptyArsenal

以前の間違った答え:

これは今日の時点で機能するはずです。 https://docs.mongodb.com/v3.2/reference/operator/projection/positional/#array-field-limitations を参照してください

クエリで_$elemMatch_を使用してクエリを実行し、次のようにプロジェクションでサブドキュメントを公開すると、正しい結果が得られるはずです。

_db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } },
                 { 'students.$': 1 } )
_

新しい答え

現在のところ、find()を使用して、サブドキュメントのリストをクエリに一致するものに制限することはできません。代わりにaggregate()を使用するか、次のいずれかの可能性を使用してください。

射影にarray-propertyを追加することで、一致するドキュメントのすべてのサブドキュメントを取得できます。

_db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } }, { 'students': 1 })
> { "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 }, { "name" : "jess", "school" : 102, "age" : 11 }, { "name" : "jeff", "school" : 108, "age" : 15 } ] }
> { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
_

または、サブドキュメントの_$elemMatch_クエリに一致する最初のアイテムを取得できます。

_db.schools.find( { zipcode: 63109, students: { $elemMatch: { school: 102 } } }, { 'students.$': 1 })
> { "_id" : 1, "students" : [ { "name" : "john", "school" : 102, "age" : 10 } ] }
> { "_id" : 4, "students" : [ { "name" : "barney", "school" : 102, "age" : 7 } ] }
_
2
SimonSimCity