2012-01-05 40 views
2

所以我使用mongoose和node.js來訪問一個mongodb數據庫。我想根據一個數字碰撞每個結果(如果沒有碰撞,它們按照創建的日期排序)。例如:如何在mongodb/mongoose查詢中基於關閉參數更改結果位置?

{ name: 'A', 
    bump: 0 }, 

{ name: 'B', 
    bump: 0 }, 

{ name: 'C', 
    bump: 2 }, 

{ name: 'D', 
    bump: 1 } 

會在訂單中retreived:C,A,d,B.這怎麼可能實現(不通過數據庫中的每個條目迭代)?

+0

所以你想要它根據1,2,1,0排序? – glortho 2012-01-05 02:58:47

+0

不,我想結果「碰到」了很多結果 – sdfadfaasd 2012-01-06 00:04:01

+0

請舉一個例子......「我有x存儲在數據庫中。一個請求進來,我想它做...」 – 2012-01-06 15:16:12

回答

1

讓我們猜你的代碼是變量response(這是一個數組),那麼我會做:

response.sort(function(obj1, obj2){ 
    return obj2.bump - obj1.bump; 
}); 

,或者如果你也想採取名記順序:

response.sort(function(obj1, obj2){ 
    var diff = obj2.bump - obj1.bump; 
    var nameDiff = (obj2.name > obj1.name)?-1:((obj2.name < obj1.name)?1:0); 
    return (diff == 0) ? nameDiff : diff; 
}); 
+0

您的第一個將返回C D A B,而不是C A D B。他希望按照顛簸移動的文檔 - A和B都有0個顛簸,所以它們保持在原來的位置。C有2個顛簸,所以它比A高2個,因此這個列表將是C A B D。但是然後D有1個凹凸,所以它上升1,高於B,所以最後的列表是C A D B. – glortho 2012-01-08 20:43:09

+0

@Jed我猜他寫錯了。我的答案是解釋凹凸爲「秩序」... – 2012-01-09 04:38:23

+0

這不會迭代列表?我承認不是一個MongoDB專家,但我不確定如何在不迭代任何語言的情況下對列表進行排序。 – gilly3 2012-01-13 22:19:48

1

我不認爲純粹的基於查詢的解決方案可能與您的文檔模式(我假設你有createdDatebump字段)。相反,我建議叫sortorder,讓您所需檢索訂單跟蹤單場:

  1. sortorder最初創建時間戳。如果沒有「顛簸」,按此字段進行排序會提供正確的順序。
  2. 如果出現「凹凸」,sortorder將失效。因此,只需更正sortorder的值:每次發生「顛簸」時,都會將顛簸文檔的sortorder字段與直接位於其前面的文檔進行交換。這實際上按照排序順序「顛簸」文檔。
  3. 查詢時,按sortorder排序。

如果在別處沒有使用,您可以刪除字段bumpcreatedDate


另外,大多數社交網站並不直接根據投票數(或「顛簸」)來操縱帖子的展示位置。相反,票數用於計算得分。然後帖子按這個分數排序和顯示。在你的情況下,你應該將createdDatebumps組合成一個單一的分數,可以在查詢中排序。

本網站(StackOverflow.com)有關於如何確定「熱門」問題的相關meta discussion。我認爲甚至有一場比賽想出一個新的公式。元問題還分享了其他兩個流行的社交新聞網站使用的公式:Y Combinator Hacker News和Reddit。

1

不是一個愉快的答案,但您要求的解決方案是不現實的。以下是我的建議:

  1. OrderPosition屬性添加到您的對象而不是凹凸。

  2. 認爲「碰撞」是一個事件。它最好表現爲一個事件處理函數。當某件商品被商業邏輯中的任何觸發器「碰撞」時,需要調整商品的集合。

    var currentOrder = this.OrderPosition 
    this.OrderPosition = currentOrder - bump; // moves your object up the list 
    // write a foreach loop here, iterating every item AFTER the items unadjusted 
    // order, +1 to move them all down the list one notch.  
    

這確實需要通過許多項目迭代,我知道你正試圖阻止,但我不認爲有任何其他的方式來安全地確保您的項目排序的完整性 - 特別是當相對於後來發生的其他拉集合。

+0

我認爲你的方法是正確的,但你的實現是關閉的。你所要做的就是在項目前面交換地點。你不需要迭代列表,除非找到前一個項目。 – gilly3 2012-01-13 22:23:41

+0

@ gilly3如果它僅僅是一個列表對象,並且你正在交換位置,那麼你是正確的。但據我瞭解,持久性收集中的每個項目都有一個訂單,如果有任何項目被移動,其他項目必須進行調整。通過字段保持對象本身的值意味着每條記錄都需要更新。相當沒有效率,但不知道太多這個問題我不能提供更好的解決方案。 :) – 2012-01-13 22:58:38

2

嘗試這樣的事情。存儲一個跟蹤總線數的計數器,我們稱之爲thread_count,最初設置爲0,所以有一個文件看起來像{thread_count:0}

每次創建一個新的線程,使用{$inc : {thread_count:1}}作爲改性劑第一次調用findAndModify() - 即由1遞增計數器並返回其新值。

然後,當您插入新線程時,將計數器的新值用作文檔中字段的值,我們將其稱爲post_order

因此,您插入的每個文檔每次的值都大於1。例如,插入第一個3個文件應該是這樣的:

{name:'foo', post_order:1, created_at:... } // value of thread_count is at 1 {name:'bar', post_order:2, created_at:... } // value of thread_count is at 2 {name:'baz', post_order:3, created_at:... } // value of thread_count is at 3

那麼有效,你可以通過post_order存在上升查詢和秩序,它會在他們返回最舊到最新的順序(或從最新到最舊的降序)。

然後,如果線條在其投票順序中按其排列順序「碰撞」,則可以在{$inc:{post_order:1}}的文檔上調用update()。這將按照結果排序順序將其前進1。如果兩個線程對於post_order具有相同的值,created_at將區分哪一個先到達。所以你會按post_order, created_at排序。

您需要索引post_ordercreated_at