2016-11-16 12 views
1

MongoDb集約の$group引数に関する質問があります。次のように私のデータ構造が見えます:

マイ"イベント"コレクションは、この単一のドキュメントが含まれています

{ 
    "_id": ObjectId("mongodbobjectid..."), 
    "name": "Some Event", 
    "attendeeContainer": { 
     "min": 0, 
     "max": 10, 
     "attendees": [ 
      { 
       "type": 1, 
       "status": 2, 
       "contact": ObjectId("mongodbobjectidHEX1") 
      }, 
      { 
       "type": 7, 
       "status": 4, 
       "contact": ObjectId("mongodbobjectidHEX2") 
      } 
     ] 
    } 
} 

マイ"連絡先"コレクションはこれらの文書が含まれています

{ 
    "_id": ObjectId("mongodbobjectidHEX1"), 
    "name": "John Doe", 
    "age": 35 
}, 
{ 
    "_id": ObjectId("mongodbobjectidHEX2"), 
    "name": "Peter Pan", 
    "age": 60 
} 

何I "イベント"コレクションのaggregateクエリを実行し、fulを使用して次の結果を取得しますL「連絡先」データ:

"$unwind" : "$attendeeContainer.attendees", 
"$lookup" : { "from" : "contactinfo", "localField" : "attendeeContainer.attendees.contact","foreignField" : "_id", "as" : "contactInfo" }, 
"$unwind" : "$contactInfo", 
"$group" : { "_id": "$_id", 
       "name": { "$first" : "$name" }, 
       ... 
       "contact": { "$push": { "contact": "$contactInfo"} } 
      } 

しかし、これは「接触」配列は、「イベント」であることにつながる:

{ 
    "_id": ObjectId("mongodbobjectid..."), 
    "name": "Some Event", 
    "attendeeContainer": { 
     "min": 0, 
     "max": 10, 
     "attendees": [ 
      { 
       "type": 1, 
       "status": 2, 
       "contact": { 
        "_id": ObjectId("mongodbobjectidHEX1"), 
        "name": "John Doe", 
        "age": 35 
       } 
      }, 
      { 
       "type": 7, 
       "status": 4, 
       "contact": { 
        "_id": ObjectId("mongodbobjectidHEX2"), 
        "name": "Peter Pan", 
        "age": 60 
       } 
      } 
     ] 
    } 
} 

私は(短縮版)は次のようになり、今使っているの引数各「attendeeContainer.attendees」にあるアレイの1つのドキュメントではなく、(グループ化されているため) 「連絡先」配列を「attendeeContainer.attendees」にプッシュするには?私が試したようなもの

(上記所望の出力に示すように):明らかに許可されていません

"attendeeContainer.attendees.contact": { "$push": { "contact": "$contactInfo"} } 

しかし、MongoDBのを「」 $groupステージ。

db.event.aggregate([ 
    { "$unwind": "$attendeeContainer.attendees" }, 
    { 
     "$lookup" : { 
      "from" : "contactinfo", 
      "localField" : "attendeeContainer.attendees.contact", 
      "foreignField" : "_id", 
      "as" : "attendeeContainer.attendees.contactInfo" 
     } 
    }, 
    { "$unwind": "$attendeeContainer.attendees.contactInfo" }, 
    { 
     "$group": { 
      "_id" : "$_id", 
      "name": { "$first": "$name" }, 
      "min" : { "$first": "$attendeeContainer.min" }, 
      "max" : { "$first": "$attendeeContainer.max" }, 
      "attendees": { "$push": "$attendeeContainer.attendees" }    
     } 
    }, 
    { 
     "$project": { 
      "name": 1, 
      "attendeeContainer.min": "$min", 
      "attendeeContainer.max": "$min", 
      "attendeeContainer.attendees": "$attendees" 
     } 
    } 
]) 

デバッグのヒント

でパイプラインをデバッグ:

+0

待ち時間!自分の[質問](https://stackoverflow.com/questions/40609209/mongodb-lookup-query-with-multiple-fields-from-objects-array)の複製を作成しましたか? – styvane

+0

いいえ、私はしませんでした。前の質問は$ルックアップクエリに関連していました。これはグループ化に関連し、より複雑なシナリオを特徴とします。 –

答えて

1

は鍵がattendeeContainerサブドキュメントを作成するために、最終的な$projectパイプラインを使用している、以下の集約パイプラインを実行してみてください第4ステージでは、結果は

​​

パイプラインの結果

{ 
    "_id" : ObjectId("582c789282a9183adc0b53f5"), 
    "name" : "Some Event", 
    "min" : 0, 
    "max" : 10, 
    "attendees" : [ 
     { 
      "type" : 1, 
      "status" : 2, 
      "contact" : ObjectId("582c787682a9183adc0b53f3"), 
      "contactInfo" : { 
       "_id" : ObjectId("582c787682a9183adc0b53f3"), 
       "name" : "John Doe", 
       "age" : 35 
      } 
     }, 
     { 
      "type" : 7, 
      "status" : 4, 
      "contact" : ObjectId("582c787682a9183adc0b53f4"), 
      "contactInfo" : { 
       "_id" : ObjectId("582c787682a9183adc0b53f4"), 
       "name" : "Peter Pan", 
       "age" : 60 
      } 
     } 
    ] 
} 

と最終$projectパイプラインはあなたの望ましい結果が得られます:

db.event.aggregate([ 
    { "$unwind": "$attendeeContainer.attendees" }, 
    { 
     "$lookup" : { 
      "from" : "contactinfo", 
      "localField" : "attendeeContainer.attendees.contact", 
      "foreignField" : "_id", 
      "as" : "attendeeContainer.attendees.contactInfo" 
     } 
    }, 
    { "$unwind": "$attendeeContainer.attendees.contactInfo" }, 
    { 
     "$group": { 
      "_id": "$_id", 
      "name": { "$first": "$name" }, 
      "min" : { "$first": "$attendeeContainer.min" }, 
      "max" : { "$first": "$attendeeContainer.max" }, 
      "attendees": { "$push": "$attendeeContainer.attendees" }    
     } 
    }, 
    { 
     "$project": { 
      "name": 1, 
      "attendeeContainer.min": "$min", 
      "attendeeContainer.max": "$min", 
      "attendeeContainer.attendees": "$attendees" 
     } 
    }/**/ 
]) 

希望/実際の出力

{ 
    "_id" : ObjectId("582c789282a9183adc0b53f5"), 
    "name" : "Some Event", 
    "attendeeContainer" : { 
     "min" : 0, 
     "max" : 10, 
     "attendees" : [ 
      { 
       "type" : 1, 
       "status" : 2, 
       "contact" : ObjectId("582c787682a9183adc0b53f3"), 
       "contactInfo" : { 
        "_id" : ObjectId("582c787682a9183adc0b53f3"), 
        "name" : "John Doe", 
        "age" : 35 
       } 
      }, 
      { 
       "type" : 7, 
       "status" : 4, 
       "contact" : ObjectId("582c787682a9183adc0b53f4"), 
       "contactInfo" : { 
        "_id" : ObjectId("582c787682a9183adc0b53f4"), 
        "name" : "Peter Pan", 
        "age" : 60 
       } 
      } 
     ] 
    } 
} 
+0

ありがとうございます。'$ project'引数は"出席者 "を配置します。グループ化を「より簡単に」する方法はありますか?私は実際には、常に**イベントの文書と連絡先の文書の両方から**すべてのデータ**を取得したいと思っています。上に示したのは完全な "イベント"文書のほんの一部です(実際はもっと大きくなります)。すべての単一フィールドに対してグループ化を作成せずに必要な出力を実行する方法はありますか? –

+0

残念ながら、 '$ group'パイプラインでは、SQLのGROUP BY句に似た、必要なフィールドを指定する必要があります。 SQLでは、集計関数のいずれかを使用しないかぎり、GROUP BYは使用できません。同じように、MongoDBでも集約関数を使用する必要があります。 'aggregate()'関数の外側で '$ group'パイプラインオブジェクトを動的に作成することができない限り、このアプローチは少し複雑です。最初に必要なキーのリストを取得するメカニズムが必要で、mapReduceのクエリが必要です。 – chridam

+0

さて、ありがとう、それはバマーです。私の "イベント"文書は50以上のフィールドを持っていますので、最初にすべてのフィールドをグループ化してから投影してみると、巨大なクエリが発生するので、実際には私にとってはオプションではありません。 –

関連する問題