我知道这应该很简单,但我无法解决如何做到这一点尽管今天花了几个小时看它。据我所知,似乎没有一个简单的在线示例或教程。
我在CouchDB数据库中有几个文档“表”,每个“表”在文档的“模式”字段中具有不同的值。具有相同模式的所有文档都包含相同的字段集。我想要做的就是能够以CSV格式查看不同的“表格”,我不想在每个模式中指定字段名列表。
CSV输出将被R脚本消耗,所以如果我能避免它,我不希望输出中有任何额外的标题;只是字段名列表,逗号分隔,CSV格式的值。
例如,“table1”格式的两条记录可能如下所示:
{
"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列表功能应该是什么样的?
提前致谢
答案 0 :(得分: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的建议不同,列表中包含的字段在此函数中是不可配置的,并且必须写入顺序或包含字段的任何更改。您还必须重写所需的任何引用逻辑。
答案 1 :(得分:1)
这是Max Ogden撰写的一些通用代码。虽然它是以node-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;