最近我一直在玩MongoDB的聚合框架,並認爲這將是一個很好的解決方案,我一直試圖圍繞我的頭。使用MongoDB聚合框架進行不同的排序和分組
所以,說我寫的討論板軟件和我有帖子下面的文檔結構:
{
'_id': ObjectId,
'created_at': datetime,
'poster_id': ObjectId,
'discussion_id': ObjectId,
'body': string
}
而且我有以下的(簡化)樣本存儲在posts
集合中的文檔:
{
'_id': 1,
'created_at': '2013-08-18 12:00:00',
'poster_id': 1,
'discussion_id': 1,
'body': 'imma potato'
}
{
'_id': 2,
'created_at': '2013-08-18 13:00:00',
'poster_id': 1,
'discussion_id': 1,
'body': 'im still a potato'
}
{
'_id': 3,
'created_at': '2013-08-18 14:00:00',
'poster_id': 2,
'discussion_id': 1,
'body': 'you are definitely a potato'
}
{
'_id': 4,
'created_at': '2013-08-18 15:00:00',
'poster_id': 3,
'discussion_id': 1,
'body': 'Wait... he is potato?'
}
{
'_id': 5,
'created_at': '2013-08-18 16:00:00',
'poster_id': 2,
'discussion_id': 1,
'body': 'Yes! He is potato.'
}
{
'_id': 6,
'created_at': '2013-08-18 16:01:00',
'poster_id': 3,
'discussion_id': 1,
'body': 'IF HE IS POTATO... THEN WHO WAS PHONE!?'
}
我想要做的是返回一個明確的地圖poster_id
s與他們的最新帖子_id
按最新文章降序排列。因此,在最後,考慮到上面的示例代碼,映射看起來非常相似:
{
3:6,
2:5,
1:2
}
這裏是我使用Python中pymongo的執行MongoDB的聚合框架的寫了一個方法的一個例子:
def get_posters_with_latest_post_by_discussion_ids(self, discussion_ids, start=None, end=None, skip=None, limit=None, order=-1):
'''Returns a mapping of poster ids to their latest post associated with
the given list of discussion_ids. A date range, ordering and paging properties
can be applied.
'''
pipelines = []
if order:
pipelines.append({ '$sort': { 'created_at': order } })
if skip:
pipelines.append({ '$skip': skip })
if limit:
pipelines.append({ '$limit': limit })
match = {
'discussion_id': {
'$in': discussion_ids
}
}
if start and end:
match['created_at'] = {
'$gte': start,
'$lt': end
}
pipelines.append({ '$match': match })
pipelines.append({ '$project': { 'poster_id': '$poster_id' } })
pipelines.append({ '$group': { '_id': '$poster_id', 'post_id': { '$first': '$_id' } } })
results = self.db.posts.aggregate(pipelines)
poster_to_post_map = {}
for result in results['result']:
poster_to_post_map[result['_id']] = result['post_id']
return poster_to_post_map
現在我已經有了映射,我可以分別查詢posters
和posts
集合以查看完整文檔,然後將它們組合在一起顯示。
現在,問題不是它不起作用,而是......種。假設我的帖子數量要多得多,我想通過他們的最新帖子翻閱海報清單。如果我的頁面限制是「每頁10張海報」,並且在最終的10個文檔中存在一個包含2個或更多帖子的單個海報,我實際上在我的地圖中返回的項目少於10個。
例如,我有10個帖子,1個帖子在初始結果中有3個帖子。然後,彙總框架將放棄其他2個帖子,並將最新消息與該用戶相關聯,從而生成包含8個條目的地圖,而不是10個。
這非常令人沮喪,因爲我無法可靠地對結果進行分頁。我也無法準確確定我是否在結果的最後一頁,因爲一組結果可能會或可能不會返回0個或更多匹配。
什麼,如果有的話,我在這裏做錯了嗎?
我試圖做到的是足夠簡單和聚合框架似乎是一個非常適合我的問題。
這將是足夠簡單,如果它是一個傳統的關係型數據庫的存儲過程,但是這就是我們,當我們移動到無模式文檔存儲犧牲;關係在數據庫的上下文之外進行管理。
無論如何,代碼應該很容易遵循,我會回答你可能有的任何問題。
無論哪種方式,感謝您抽出時間來閱讀。:)
編輯:解決
這裏是未來的觀衆解決方案的要點是:https://gist.github.com/wilhelm-murdoch/6260469
我的F - 國王發誓基督,但總有一些平凡的小細節我似乎忽視。主席先生,恐怕我只有一票可供。謝謝! **致敬 –
另外,對於未來的其他人,這裏有一個要點我一起來說明@ kmfk的解決方案:https://gist.github.com/wilhelm-murdoch/6260469 –
@WilhelmMurdoch - 很高興爲您提供幫助。 :] – kmfk