2011-03-04 33 views
3

我可以使用一些幫助過濾來自couchdb視圖的不同值。 我有一個數據庫,存儲有關計算機信息的日誌。 計算機的定期新記錄被寫入數據庫。CouchDB - 從列表中篩選每個記錄實例的最新日誌

有點簡化的I存儲條目這樣的:

{ 
    "name": "NAS", 
    "os": "Linux", 
    "timestamp": "2011-03-03T16:26:39Z", 
} 
{ 
    "name": "Server1", 
    "os": "Windows", 
    "timestamp": "2011-02-03T19:31:31Z", 
} 
{ 
    "name": "NAS", 
    "os": "Linux", 
    "timestamp": "2011-02-03T18:21:29Z", 
} 

到目前爲止,我很努力來過濾該列表由不同的條目。 我想收到的是每個設備的最新日誌文件。

我有這樣一個觀點:

function(doc) { 
    emit([doc.timestamp,doc.name], doc); 
} 

林查詢這一觀點與Python(couchdbkit),我想出了這麼遠看起來像這樣的最佳解決方案:

def get_latest_logs(cls): 
    unique_names = [] 
    unique = [] 
    for log in cls.view("logs/timestamp", descending=True): 
     if log.name not in unique_names: 
      unique_names.append(log.name) 
      unique.append(log) 
    return unique 

好。 ..這工作。但是我有強烈的感覺,這不是python需要迭代整個logfiles列表(可能會變得很長)的最佳解決方案。

我想我需要一個減少功能,但我真的找不到任何例子 或解釋我可以適應我的問題。

所以,我正在尋找的是一個(純粹的couchdb)視圖,只是吐出給定設備的最新日誌。

感謝, 安德烈亞斯

回答

6

這是我做的。這是CouchDB濫用的邊界,但我已經取得了很大的成功。

通常,reduce將計算一個總數或一個計數或類似的東西。不過,把減少看作淘汰賽。許多價值觀進來了,只有一個出來。減少!重複一遍又一遍,你有最終的勝利者(重新減少)。在這種情況下,具有最新時間戳的日誌是勝利者。

當然,welterweights不能打重量級。必須有聯賽和體重類。它只對某些文件與某些其他文件做類似的文件有意義。這正是減少參數所要做的。它將確保只有均勻匹配的角鬥士才能進入血液運送中的鋼筋籠。 (正在踢咖啡。)

首先,發出設備鍵入的所有日誌。發出的value只是文檔的副本。

function(doc) { 
    emit(doc.name, doc); 
} 

接下來,編寫reduce函數以返回所有給定值的最新時間戳。如果你看到來自不同聯賽的兩名角鬥士(來自不同系統的兩個日誌)之間的戰鬥,請停止戰鬥!出錯了(有人查詢時沒有正確的group值)。

function(keys, vals, re) { 
    var challenger, winner = null; 
    for(var a = 0; a < vals.length; a++) { 
     challenger = vals[a]; 
     if(!winner) { 
      // The title is unchallenged. This value is the winner. 
      winner = challenger; 
     } else { 
      // Fight! 
      if(winner.name !== challenger.name) { 
       // Stop the fight! He's gonna kill him! 
       return null; // With a grouping query, this will never happen. 
      } else if(winner.timestamp > challenger.timestamp) { 
       // The champ wins! (Nothing to do.) 
      } else { 
       // The challenger wins! 
       winner = challenger; 
      } 
     } 
    } 

    // Today's champion lives to fight another day. 
    return winner; 
} 

(注意,時間戳的比較可能是錯誤的。你將不得不轉換爲Date可能。)

現在,當您使用?group=true查詢視圖時,那麼CouchDB將只使用與您的計算機名稱相同的key來減少(找到中獎者)值。

(您也可以發出一個數組作爲重點,這給了更多的靈活性。你可以emit([doc.name, doc.timestamp], doc)來代替。所以,你可以看到系統的所有日誌與像?reduce=false&startkey=["NAS", null]&endkey=["NAS", {}]查詢或者你可以通過系統?group_level=1看到最新的日誌

最後,「停止戰鬥」的東西是可選的,你可以總是返回最新的時間戳文件,但我更喜歡把它保留在那裏,因爲在類似的情況下,我想看看我是否是地圖 - 還原不正確,一個空的減少輸出是我的大腦線索。

+0

謝謝。這很好。什麼是一個不錯的電影回答:-) P.S.我會盡快給它一個upvote ;-) – arie 2011-03-06 19:39:54