2014-09-05 54 views
3

我有這個問題,我想基於從另一個集合的字段值的查詢結果進行排序,如何通過加權值排序

問題:我想先獲得用戶123周的朋友和然後得到自己的崗位,然後進行排序與​​朋友強度值後,

我有這樣的:

POST COLLECTON: 
{ 
    user_id: 8976, 
    post_text: 'example working', 
} 
{ 
    user_id: 673, 
    post_text: 'something', 
} 

USER COLLECTON: 
{ 
    user_id: 123, 
    friends: { 
     {user_id: 673,strength:4} 
     {user_id: 8976,strength:1} 
    } 
} 

回答

3

根據您從您檢索到的信息[R用戶基本上你想出來一個aggregation framework查詢,看起來像這樣:

db.posts.aggregate([ 
    { "$match": { "user_id": { "$in": [ 673, 8976 ] } } }, 
    { "$project": { 
     "user_id": 1, 
     "post_text": 1, 
     "weight": { 
      "$cond": [ 
       { "$eq": [ "$user_id", 8976 ] }, 
       1, 
       { "$cond": [ 
        { "$eq": [ "$user_id", 673 ] }, 
        4, 
        0 
       ]} 
      ] 
     } 
    }}, 
    { "$sort": { "weight": -1 } } 
]) 

那麼,爲什麼聚集在這不聚集?正如你所看到的,聚合框架不僅僅是聚合。在這裏它被用來將一個新的領域「投射」到文檔中,並用「權重」來填充它。這使您可以按照您希望排序的值重新排序結果。

當然,您需要以「生成」的方式從您的初始數據中獲取此表單,您可以爲任何數據執行此操作。這需要幾個步驟,但在這裏我將介紹JavaScript的方式來做到這一點,它應該很容易轉換到大多數語言

也假設你的實際「用戶」看起來更像這樣,這將是有效的:

{ 
    "user_id": 123, 
    "friends": [ 
     { "user_id": 673, "strength": 4 }, 
     { "user_id": 8976, "strength": 1 } 
    ] 
} 

從這樣一個對象,那麼你構建聚合管道:

// user is the structure shown above 

var stack = []; 
args = []; 

user.friends.forEach(function(friend) { 

    args.push(friend.user_id); 

    var rec = { 
     "$cond": [ 
      { "$eq": [ "user_id", friend.user_id ] }, 
      friend.strength 
     ] 
    }; 

    if (stack.length == 0) { 
     rec["$cond"].push(0); 
    } else { 
     var last = stack.pop(); 
     rec["$cond"].push(last); 
    } 

    stack.push(rec); 

}); 


var pipeline = [ 
    { "$match": { "user_id": { "$in": args } } }, 
    { "$project": { 
     "user_id": 1, 
     "post_text": 1, 
     "weight": stack[0] 
    }}, 
    { "$sort": { "weight": -1 } } 
]; 

db.posts.aggregate(pipeline); 

,這是所有有給它。現在,您有一些代碼可以查看用戶的「朋友」列表,並構建另一個查詢以獲取來自這些朋友的所有帖子,並根據每個朋友的「強度」值進行加權。

當然,你可以通過只刪除或更改$match,但保持「重」投影,你可以「浮動」所有的「朋友」的帖子在做很多同樣的事情對所有職位查詢最佳。

+0

感謝您的回答,這就是我一直在尋找的,但是有一個問題,這種方法是否經過了優化,並且足夠快,可以同時用於許多用戶? – Kordkandi 2014-09-05 10:19:45

+1

@Kordkandi這裏的實際處理與使用投影字段和'.sort()'的'.find()'操作並沒有太大的不同,它具有計算字段的優勢,否則不可能使用'。找到()'。數據庫服務器應該比應用程序服務器更快,並且您也可以在服務器上限制和分頁結果。如果每個用戶有超過500個「freinds」,那麼你不應該使用數組,而並行查詢是選項。但是這很快,無論20個或更多的朋友看起來有多複雜 – 2014-09-05 10:33:30

+0

非常感謝,你是我日常問題的答案;) – Kordkandi 2014-09-05 10:35:44