switching to node couchapp structure, redoing headers mapreduce

This commit is contained in:
Max Ogden 2011-06-20 17:45:19 -07:00
parent 25db477531
commit ae9f0b17f2
23 changed files with 105 additions and 207 deletions

1
.couchapprc Normal file
View File

@ -0,0 +1 @@
{}

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

102
app.js Normal file
View File

@ -0,0 +1,102 @@
var couchapp = require('couchapp')
, path = require('path')
;
ddoc =
{ _id:'_design/removalist'
, rewrites :
[ {from:"/", to:'pages/index.html'}
, {from:"csv", to:'_list/csv/all'}
, {from:"headers", to:'_list/urlencode/headers', query: {group: true}}
, {from:"/api", to:'../../'}
, {from:"/api/*", to:'../../*'}
, {from:"/*", to:'*'}
]
}
;
ddoc.views = {
/**
* A simple map function mocking _all, but allows usage with lists etc.
*/
all: {
map: function(doc) {
emit(doc.id, doc);
}
},
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))[0];
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");
}
},
/**
* Returns the urlencoded version of the view's keys
*
* @author Max Ogden
*/
urlencode: function(head, req) {
start({"headers":{"Content-Type" : "application/json"}});
if ('callback' in req.query) send(req.query['callback'] + "(");
var headers = [];
while (row = getRow()) {
headers.push(row.key);
}
send(escape(JSON.stringify(headers)));
if ('callback' in req.query) send(")");
}
}
ddoc.validate_doc_update = function (newDoc, oldDoc, userCtx) {
if (newDoc._deleted === true && userCtx.roles.indexOf('_admin') === -1) {
throw "Only admin can delete documents on this database.";
}
};
couchapp.loadAttachments(ddoc, path.join(__dirname, 'attachments'));
module.exports = ddoc;

View File

Before

Width:  |  Height:  |  Size: 87 B

After

Width:  |  Height:  |  Size: 87 B

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@ -1,35 +0,0 @@
/**
* 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
*/
function(head, req) {
if ('headers' in req.query) {
var headers = JSON.parse(unescape(req.query.headers))[0];
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);
send("\"" + value.replace(/\"/g, '""') + "\"");
} 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");
}
};

View File

@ -1,28 +0,0 @@
/**
* Generates a simple array of json objects representing each doc in the db
* @author Max Ogden
*/
function(head, req) {
var row, out, sep = '\n';
start({"headers":{"Content-Type" : "application/json"}});
if ('callback' in req.query) send(req.query['callback'] + "(");
send('[');
while (row = getRow()) {
for (var header in row.value) {
if (row.value[header]) {
var value = row.value[header];
if (typeof(value) == "object") {
row.value[header] = "\"" + JSON.stringify(value) + "\"";
}
}
}
send(sep + JSON.stringify(row.value));
sep = ',\n';
}
send("]");
if ('callback' in req.query) send(")");
};

View File

@ -1,28 +0,0 @@
/**
* Generates a simple array of json objects representing each doc in the db
* @author Max Ogden
*/
function(head, req) {
var row, out, sep = '\n';
start({"headers":{"Content-Type" : "application/json"}});
if ('callback' in req.query) send(req.query['callback'] + "(");
send('{');
while ((row = getRow())) {
for (var header in row.value) {
if (row.value[header]) {
var value = row.value[header];
if (typeof(value) == "object") {
row.value[header] = "\"" + JSON.stringify(value) + "\"";
}
}
}
send(sep + '"":' + JSON.stringify(row.value));
sep = ',\n';
}
send("]");
if ('callback' in req.query) send(")");
};

View File

@ -1,22 +0,0 @@
/**
* Returns the urlencoded version of the view value
*
* @author Max Ogden
*/
function(head, req) {
// Send the same Content-Type as CouchDB would
if (req.headers.Accept.indexOf('application/json')!=-1)
start({"headers":{"Content-Type" : "application/json"}});
else
start({"headers":{"Content-Type" : "text/plain"}});
if ('callback' in req.query) send(req.query['callback'] + "(");
var rows = []
while (row = getRow()) {
rows.push(row.value)
}
send(escape(JSON.stringify(rows)));
if ('callback' in req.query) send(")");
};

View File

@ -25,6 +25,4 @@ After you install it, visit this link to open Removalist:
You'll have to get yourself a couch. The easiest way is from [the instructions on this page](http://couchone.com/get). Once it's going, open up `http://YOURCOUCH/_utils` and create a new database to store your data. You'll have to get yourself a couch. The easiest way is from [the instructions on this page](http://couchone.com/get). Once it's going, open up `http://YOURCOUCH/_utils` and create a new database to store your data.
You can either replicate the couchapp from my couch [max.couchone.com/apps/_design/removalist](http://max.couchone.com/apps/_design/removalist) (quickest option) or, if you want to hack on the removalist source code first, you'll need to install the [CouchApp command line utility](http://couchapp.org/page/installing) and check out this repo. You can either replicate the couchapp from my couch [max.couchone.com/apps/_design/removalist](http://max.couchone.com/apps/_design/removalist) (quickest option) or, if you want to hack on the removalist source code first, you'll need to install `mikeal/node.couchapp.js` and clone this repo.
If you want to hack on removalist, once you have the couchapp utility working, <code>git clone</code> this repo and go into this folder and execute <code>couchapp init</code>. To upload removalist into your couch just run <code>couchapp push http://YOURCOUCH/DATABASENAME</code>. Otherwise see the Quick install section above.

View File

@ -1,50 +0,0 @@
[
{
"to": "style/*",
"from": "style/*"
},
{
"to": "script/*",
"from": "script/*"
},
{
"to": "pages/*",
"from": "pages/*"
},
{
"to": "images/*",
"from": "images/*"
},
{
"to": "pages/index.html",
"from": ""
},
{
"to": "_list/csv/all",
"from": "csv"
},
{
"to": "_list/urlencode/headers",
"from": "headers"
},
{
"to": "./",
"from": "ddoc"
},
{
"to": "./",
"from": "api/_design/ddoc"
},
{
"to": "./*",
"from": "api/_design/ddoc/*"
},
{
"to": "../../",
"from": "api"
},
{
"to": "../../*",
"from": "api/*"
}
]

View File

@ -1,7 +0,0 @@
/**
* A simple map function mocking _all, but allows usage with lists etc.
*
*/
function(doc) {
emit(doc.id, doc);
}

View File

@ -1,12 +0,0 @@
/**
* Returns an array of all of the keys in the document.
*
* @author Max Ogden
*/
function(doc) {
var keys = [];
for (var key in doc) {
keys.push(key);
}
emit(doc, keys);
}

View File

@ -1,22 +0,0 @@
/**
* Reduces the passed in view headers to a list of unique object key attributes
*
* @author Max Ogden
*/
function(keys, values, rereduce) {
function include(arr, obj) {
return (arr.indexOf(obj) != -1);
}
var headers = [];
for (var doc in values) {
for (var header in values[doc]) {
if(!include(headers, values[doc][header])) {
headers.push(values[doc][header]);
}
}
}
return headers;
}