2015-08-25 167 views
2

我有一個集合,關係到其他收藏品,我想選擇的記錄了用戶最相關的選擇如下:有this.some_collection_id ==「someid」mongodb排序/查詢計算值聚合框架?

首先記錄& & this.another_collection_id = =「another_id」 然後有this.some_collection_id ==「someid」 然後有this.another_collection_id ==「another_id」 那麼其他記錄

例如記錄記載:比方說,主要收集故事,每個故事都有一個'interest_group'和一個位置'。所有用戶都有「主要興趣小組」和「地點」。我想查詢一個特定用戶的前100個最有趣的故事,同一個興趣組的故事&位置應該權衡5,同一個利益組只有3, d喜歡在查詢過程中授予這些點數,以便我可以根據這些點對故事集合進行排序並返回前100名。

因此,我可以做4個單獨的查詢併合並結果客戶端(不太漂亮)或我可以嘗試按照正確的順序獲取集合。

到目前爲止,我想出了以下內容:

map = %Q{ 
    function() { 
    var score = 1; 
    if (this.some_id == "#{some_id}") { 
     score = score + 3 
    } 
    if (this.another_id == "#{another_id}") { 
     score = score + 2 
    } 

    emit(this._id, { _id: this._id, score: score }); 
    } 
} 

reduce = %Q{ 
    function(key, values) { 
    return values; 
    } 
} 

MyCollection.map_reduce(map, reduce).out(inline: true) 

這將正確地連接得分返回記錄整個集合,但是我不能排序的得分,所以我將不得不這樣做客戶端方(也醜,因爲我只需要前100記錄左右)

有沒有辦法做到這一點不同?我也檢查了聚合框架,但我沒看到這將如何解決這個特定的查詢。

+0

那麼這個問題有點大,這是沒有人觸及它的最大原因。你至少可以編輯來顯示一些示例文檔(只有幾個),以及應該與預期結果匹配的內容。這將有助於非常瞭解。 –

+0

謝謝,讓我試着添加一些相關的數據 – ahmeij

+0

請做。我想我有你的要求,但我想確定。 –

回答

2

這裏提到的問題並沒有真正解釋這裏的邏輯以及它應該如何,但是如果我確實瞭解了你的一般含義,那麼這應該與上述類似,並且還需要額外的增強功能:

MyCollection.collection.aggregate([ 
    { "$project" => { 
     "score" => { 
      "$add" => [ 
       { "$cond" => [ 
        { "$or" => [ 
         { "$eq" => [ "$some_id" => some_id_var1 ] }, 
         { "$eq" => [ "$some_id" => some_id_var2 ] }, 
         { "$eq" => [ "$some_id" => some_id_var3 ] }, 
         { "$eq" => [ "$some_id" => some_id_var4 ] } 
        ]}, 
        3, 
        0 
       ]}, 
       { "$cond" => [ 
        { "$or" => [ 
         { "$eq" => [ "$another_id" => another_id_var1 ] }, 
         { "$eq" => [ "$another_id" => another_id_var2 ] }, 
         { "$eq" => [ "$another_id" => another_id_var3 ] }, 
         { "$eq" => [ "$another_id" => another_id_var4 ] } 
        ]}, 
        2, 
        0 
       ]}, 
       1 
      ] 
     } 
    }}, 
    { "$sort" => { "score" => -1 } }, 
    { "$limit" => 100 } 
]) 

本質上,這是在兩個「SOME_ID」和完全一樣的東西「another_id」字段進行比較對一些變量輸入,看看它們是否匹配,並返回一個分值。我在這裏做的補充是你提到「4 queries」,這樣聽起來像變化的變化。在這兩種情況下,這應該僅適用於$or條件。如果您真的只比較每種情況下的一個值,那麼只需刪除包裝$or

$cond運算符本身是「if/then/else」三元操作。所以第一個參數是「if」,下一個參數分別在true/false上返回。在這種情況下,您的歸屬評分或0

然後用add包裝所有文件,爲每個文檔生成「總分」,使用相同的邏輯。

另請注意,$project要求您輸出「顯式」結果中的所有字段。你的mapReduce除了_idscore什麼都沒做,所以我只是在這裏做同樣的事情。但是您可以根據需要添加其他字段。除非另外指定,否則_id當然總是隱含的,例如"_id" => 0

剩下的就是「分數」值上的$sort,排序後的總結果爲$limit。哪些是mapReduce不能做的事情。

這基本上是根據匹配的屬性添加權重,然後「排序」和「限制」結果到最高分數。另請注意,作爲「數據結構」,您要使用的彙總管道中的變量只是本地代碼,並且不需要使用mapReduce進行的「字符串化」處理。

+0

重新閱讀我必須說的問題我已經表達了自己在過去更好:)感謝閱讀,儘管它和解釋如何使用這樣的聚合框架。我已經能夠獲得概念證明查詢工作 – ahmeij