2012-03-30 62 views
1

我知道這應該很容易,但我不知道如何做到這一點,儘管今天花了幾個小時來看它。據我所知,似乎沒有一個簡單的例子或在線教程。從CouchDB創建CSV視圖

我在CouchDB數據庫中有幾個「表」文檔,每個「表」在文檔中的「模式」字段中具有不同的值。所有具有相同模式的文檔都包含一組相同的字段。我想要做的就是能夠以CSV格式查看不同的「表格」,並且我不希望在每個模式中指定字段名稱列表。

CSV輸出將被R腳本使用,所以如果我可以避免它們,我不想在輸出中添加任何其他標題;只是字段名稱列表,用CSV格式的值逗號分隔。

例如,兩個記錄在 「表1」 的格式可能類似於:

{  
    "schema": "table1", 
    "field1": 17, 
    "field2": "abc", 
    ... 
    "fieldN": "abc", 
    "timestamp": "2012-03-30T18:00:00Z" 
} 

{ 
    "schema": "table1", 
    "field1": 193, 
    "field2": "xyz", 
    ... 
    "fieldN": "ijk", 
    "timestamp": "2012-03-30T19:01:00Z" 
} 

我的觀點很簡單:

"all": "function(doc) { 
    if (doc.schema == "table1") { 
     emit(doc.timestamp, doc) 
    } 
}" 

,因爲我想按照時間戳順序排序我的記錄。

想必列表功能將是這樣的:

"csv": "function(head, req) { 
    var row; 
    ... 
    // Something here to iterate through the list of fieldnames and print them 
    // comma separated 
    for (row in getRow) { 
     // Something here to iterate through each row and print the field values 
     // comma separated 
    } 
}" 

,但我不能讓我的頭圍繞它的其餘部分。

如果我想獲得CSV輸出看起來像

"timestamp", "field1", "field2", ..., "fieldN" 
"2012-03-30T18:00:00Z", 17, "abc", ..., "abc" 
"2012-03-30T19:01:00Z", 193, "xyz", ..., "ijk" 

應該我CouchDB的列表功能是什麼樣子?

在此先感謝

回答

1

這裏是一些通用代碼,最大奧格登寫。雖然它是在節點couchapp形式,你可能得到的想法:

 
var couchapp = require('couchapp') 
    , path = require('path') 
    ; 

ddoc = { _id:'_design/csvexport' }; 

ddoc.views = { 
    headers: { 
    map: function(doc) { 
     var keys = []; 
     for (var key in doc) { 
     emit(key, 1);   
     } 
    }, 
    reduce: "_sum" 
    } 
}; 

ddoc.lists = { 
    /** 
    * Generates a CSV from all the rows in the view. 
    * 
    * Takes in a url encoded array of headers as an argument. You can 
    * generate this by querying /_list/urlencode/headers. Pass it in 
    * as the headers get parameter, e.g.: ?headers=%5B%22_id%22%2C%22_rev%5D 
    * 
    * @author Max Ogden 
    */ 
    csv: function(head, req) { 
    if ('headers' in req.query) { 
     var headers = JSON.parse(unescape(req.query.headers)); 

     var row, sep = '\n', headerSent = false, startedOutput = false; 

     start({"headers":{"Content-Type" : "text/csv; charset=utf-8"}}); 
     send('"' + headers.join('","') + '"\n'); 
     while (row = getRow()) { 
     for (var header in headers) { 
      if (row.value[headers[header]]) { 
      if (startedOutput) send(","); 
      var value = row.value[headers[header]]; 
      if (typeof(value) == "object") value = JSON.stringify(value); 
      if (typeof(value) == "string") value = value.replace(/\"/g, '""'); 
      send("\"" + value + "\""); 
      } else { 
      if (startedOutput) send(","); 
      } 
      startedOutput = true; 
     } 
     startedOutput = false; 
     send('\n'); 
     } 
    } else { 
     send("You must pass in the urlencoded headers you wish to build the CSV from. Query /_list/urlencode/headers?group=true"); 
    } 
    } 
} 

module.exports = ddoc; 

來源: https://github.com/kanso/kanso/issues/336

3

列表功能與您指定的地圖作品應該是這個樣子:

function(head,req) { 
    var headers; 
    start({'headers':{'Content-Type' : 'text/csv; charset=utf-8; header=present'}}); 
    while(r = getRow()) { 
    if(!headers) { 
     headers = Object.keys(r.value); 
     send('"' + headers.join('","') + '"\n'); 
    } 
    headers.forEach(function(v,i) { 
     send(String(r.value[v]).replace(/\"/g,'""').replace(/^|$/g,'"')); 
     (i + 1 < headers.length) ? send(',') : send('\n'); 
    }); 
    } 
} 

與Ryan的建議不同,要包含在列表中的字段在此函數中是不可配置的,並且必須寫入任何順序或包含字段的更改。您還必須重寫所需的任何引用邏輯。