2016-09-18 133 views
0

我在這裏要做的是查詢併合並多個子文檔作爲數組。我認爲聚合框架是可行的,但我似乎無法完全正確。將多個子文檔合併爲聚合投影中的數組MongoDB

下面是我收集稱爲遊客

{ 
    "_id": ObjectId("57dc5c2b7463d336ec3fff8c"), 
    "username": "Bob", 
    "fullname": "Bobby", 
    "activities": 
     { "visits" : [ 
     { 
      "_id": ObjectId("57dc674e4208b12fd4a52a3d"), 
      "date": ISODate("2016-09-18T08:00:00.000Z"), 
      "location" : "Jakarta", 
     }, 
     { 
      "_id": ObjectId("57dd3795c13c5e2b7484ea4b"), 
      "date": ISODate("2016-09-17T08:00:00.000Z"), 
      "location" : "Denpasar", 
     } 
     ], 
     "purchases" : [ 
     { 
      "_id": ObjectId("57dc4769c0f09317282b3f92"), 
      "date": ISODate("2016-09-17T07:30:00.000Z"), 
      "product_name" : "Shirt", 
      "price": 125000 
     },{ 
      "_id": ObjectId("57dbfdc6be9dcf1e7c4a1751"), 
      "date": ISODate("2016-09-18T08:30:00.000Z"), 
      "product_name" : "Shoes", 
      "price": 150000 
     } 
     ]}, 
    } 
} 

這裏是文件我想,努力實現與聚合是這樣的,有情況,我可以按日期sort他們,請使用limitskip

{ 
    "_id": ObjectId("57dc5c2b7463d336ec3fff8c"), 
    "activities": [ 
    { 
     "activity_type": "purchases", 
     "_id": ObjectId("57dbfdc6be9dcf1e7c4a1751"), 
     "date": ISODate("2016-09-18T08:30:00.000Z"), 
     "product_name" : "Shoes", 
     "price": 150000 
    },{ 
     "activity_type": "visits", 
     "visits_id": ObjectId("57dc674e4208b12fd4a52a3d"), 
     "date": ISODate("2016-09-18T08:00:00.000Z"), 
     "location" : "Jakarta", 
    },{ 
     "activity_type": "visits", 
     "visits_id": ObjectId("57dd3795c13c5e2b7484ea4b"), 
     "date": ISODate("2016-09-17T08:00:00.000Z"), 
     "location" : "Denpasar", 
    },{ 
     "activity_type": "purchases", 
     "date": ISODate("2016-09-17T07:30:00.000Z"), 
     "product_name" : "Shirt", 
     "price": 125000 
    }] 
} 

我一直在試圖用這種聚合

db.visitors.aggregate([{ 
    $match: { _id: ObjectId("57dc5c2b7463d336ec3fff8c") } }, 
    { 
     $group: { 
      _id: "$_id", 
      visits: { 
      "$addToSet": "$activities.visits" 
      }, 
      purchases: { 
      "$addToSet": "$activities.purchases" 
      } 
     } 
    }]) 

這樣做,但我沒有得到我想要的東西,它是按類型而不是僅僅將它們分組,我可以」 t甚至使用skiplimit(似乎只是跳過並限制訪問者數量)。

{ 
    "_id": ObjectId("57dc5c2b7463d336ec3fff8c"), 
    "visits": [ 
     [ 
     { 
      "_id": ObjectId("57dc674e4208b12fd4a52a3d"), 
      "date": ISODate("2016-09-18T08:00:00.000Z"), 
      "location" : "Jakarta", 
     }, 
     { 
      "_id": ObjectId("57dd3795c13c5e2b7484ea4b"), 
      "date": ISODate("2016-09-17T08:00:00.000Z"), 
      "location" : "Denpasar", 
     } 
     ] 
    ], 
    "news": [ 
     [ 
     { 
      "_id": ObjectId("57dc4769c0f09317282b3f92"), 
      "date": ISODate("2016-09-17T07:30:00.000Z"), 
      "product_name" : "Shirt", 
      "price": 125000 
     },{ 
      "_id": ObjectId("57dbfdc6be9dcf1e7c4a1751"), 
      "date": ISODate("2016-09-18T08:30:00.000Z"), 
      "product_name" : "Shoes", 
      "price": 150000 
     } 
     ] 
    ] 
} 

,我已經試過這與unwind另一個投影,

db.visitors.aggregate([ 
    { $match: { _id: ObjectId("57dc5c2b7463d336ec3fff8c") } }, 
    { $unwind: '$activities.visits' }, 
    { $unwind: '$activities.purchases' }, 
    { $project: { 
     _id: 0, 
     //visits 
     "visits_id": "$activities.visits._id", 
     "visits_date": "$activities.visits.date", 
     "visits_location" : "$activities.visits.location" 
     //purchases 
     "purchases_id": "$activities.purchases._id", 
     "purchases_date": "$activities.purchases.date", 
     "purchases_product_name": "$activities.purchases.product_name", 
     "purchases_price": "$activities.purchases.price", 
    } 
    } 
]) 
    .skip(0) 
    .limit(2) 

但似乎每個索引

{ 
    "_id": ObjectId("57dc5c2b7463d336ec3fff8c"), 
    "activities": [ 
    { 
     "purchases_id": ObjectId("57dbfdc6be9dcf1e7c4a1751"), 
     "purchases_date": ISODate("2016-09-18T08:30:00.000Z"), 
     "purchases_product_name" : "Shoes", 
     "purchases_price": 150000 
     "visits_id": ObjectId("57dc674e4208b12fd4a52a3d"), 
     "visits_date": ISODate("2016-09-18T08:00:00.000Z"), 
     "visits_location" : "Jakarta", 
    },{ 
     "purchases_id": ObjectId("57dc4769c0f09317282b3f92"), 
     "purchases_date": ISODate("2016-09-17T07:30:00.000Z"), 
     "purchases_product_name" : "Shirt", 
     "purchases_price": 125000 
     "visits_id": ObjectId("57dd3795c13c5e2b7484ea4b"), 
     "visits_date": ISODate("2016-09-17T08:00:00.000Z"), 
     "visits_location" : "Denpasar", 
    }] 
} 

在合併不同類型的文件是否有可能做這與我目前的文件?或者我應該改變我的文檔結構?

更新解決

我結束了在我的每一個陣列中的子文檔添加activity_type,並解決了這個利用$setUnion合併多個數組的數組,並使用$slice限制並跳過陣列。我不知道怎麼回事,但似乎已經$setUnion自動分揀它

db.visitors.aggregate([ 
{ 
    $project: { 
     activities: { 
      $setUnion: ['$activities.visits', '$activities.purchases'], 
     } 
    } 
}, 
{ 
    $project:{ 
     activites: { 
      $slice: ["$activities", 0, 2] 
     } 
    } 
} 
]) 
+0

'$ slice'可以像我想要的跳過和限制,但它不能解決我的問題,而'$ setUnion'正是我正在查找的 – fadeltd

回答

1

如果添加activity_type場到每個數組元素,它會很容易使用$setUnion一個aggregation階段:

db.visitors.aggregate([ 
    { 
     $project: { 
      activities: { 
       $setUnion: ['$activities.visits', '$activities.purchases'] 
      } 
     } 
    } 
]) 

在這種情況下,您將使用它們的類型將「串聯」在一起的數組組合到一個活動數組中。

對於你的問題,sortskiplimit,另一部分是聚合階段,將在每個文檔,而不是子文檔工作,所以你需要$match您需要的文件,$unwind結果從之前activities陣列,然後你可以使用全部的sortskip,limit運營商。

+1

請注意,這將從結果中篩選出重複項。 – styvane

+1

@Styvane'visited'和'purchases'都有'_id'字段,不會有重複。並且我還要求他爲它們添加'activity_type'字段 – TomG

+0

你是對的。我沒有注意到這一點。 – styvane