2016-11-16 88 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 
} 

我想要做的是在「事件」集合上執行aggregate查詢,並獲得以下結果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」處。 如何將「聯繫人」陣列推到「attendeeContainer.attendees」? (如上面的所期望的輸出)

我嘗試之類的東西:

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

但是顯然的mongodb不允許「」在$group階段。

+0

等一下!你剛剛創建了自己的[問題]的副本(https://stackoverflow.com/questions/40609209/mongodb-lookup-query-with-multiple-fields-from-objects-array)? – styvane

+0

不,我沒有。前面的問題與$查詢查詢有關。這與分組有關,並且具有更復雜的情況。 –

回答

1

嘗試運行以下聚合管道,關鍵是使用最終$project管道創建attendeeContainer子文檔:

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", 
    "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個字段,所以我想先將所有字段分組然後再投影它們對我來說不是一個真正的選擇,因爲這會導致一個巨大的查詢。 –