2013-06-11 103 views
4

我現在的聚集是:如何與賽場秩序MongoDB的聚集,排序,並限制

db.group_members.aggregate({ 
    $match: { user_id: { $in: [1,2,3] } } 
}, { 
    $group: { _id: "$group_id" } 
}, { 
    $sort: { last_post_at: -1 } 
}, { 
    $limit: 5 
}) 

有關的文檔結構:

{ 
    _id: '...', 
    user_id: '...', 
    group_id: '...', 
    last_post_at: Date, 
} 

我也得到了一個指數{user_id: 1, last_post_at: -1}

由於我的索引已經在last_post_at是無用的?我不是100%確定這是如何排序的。

我的最終目標是複製這個SQL:

SELECT DISTINCT ON (group_id) 
FROM group_members 
WHERE user_id in [1,2,3] 
ORDER_BY last_post_at DESC 
LIMIT 5 

我不知道如何使它高性能一個非常大的group_members,仍然以正確的順序返回。

更新: 我希望找到一個解決方案,將限制文件加載到內存中的數量。這將是一個相當大的收集和訪問非常頻繁。

+0

你缺少$ group階段的分組操作 - 你想要last_post:{$ max:「$ last_post_at」}或類似的東西。 –

+0

那還是不需要將user_id:{$ in:[1,2,3]}的整個子集存儲在內存中嗎? – Tal

+0

該小組必須通過所有匹配的文檔 - 因爲您的排序和限制是基於*聚合*值,因此它不能在組之前進行限制。可以想象,優化是可能的,將排序和限制每個user_id值在組之前,但目前沒有在2.4 MongoDB中實現。 –

回答

4

將$ sort放在$ group之前,否則MongoDB不能使用該索引來幫助排序。

但是,在您的查詢中,您希望查詢與您的group_members集合的總大小相比相對較少數量的user_ids。所以我只推薦一個user_id的索引。在這種情況下,MongoDB將不得不通過last_post_at對內存中的結果進行排序,但這是值得的,以便爲user_id的初始查找使用索引。

+0

不排序首先將整個集合加載到內存中? – Tal

+0

不,如果您在排序字段上有索引,則不行。如果你確實有這樣一個索引,MongoDB將按照排序順序迭代它。否則,它會嘗試對內存中的所有內容進行排序,如果使用超過10%(我認爲)的RAM,則會中止。 –

+0

我結束了第二個選擇,在一些基準測試結束後,比我預期的要快得多。 – Tal