to use nano you need to connect it to your couchdb install, to do that:
var nano = require('nano')('http://localhost:5984');
to create a new database:
nano.db.create('alice');
and to use it:
var alice = nano.db.use('alice');
in this examples we didn’t specify a callback function, the absence of a
callback means “do this, ignore what happens”.
in nano the callback function receives always three arguments:
err - the error, if any
body - the http response body from couchdb, if no error.
json parsed body, binary for non json responses
header - the http response header from couchdb, if no error
a simple but complete example using callbacks is:
var nano = require('nano')('http://localhost:5984');
// clean up the database we created previously
nano.db.destroy('alice', function() {
// create a new database
nano.db.create('alice', function() {
// specify the database we are going to use
var alice = nano.use('alice');
// and insert a document in it
alice.insert({ crazy: true }, 'rabbit', function(err, body, header) {
if (err) {
console.log('[alice.insert] ', err.message);
return;
}
console.log('you have inserted the rabbit.')
console.log(body);
});
});
});
if you run this example(after starting couchdb) you will see:
you have inserted the rabbit.
{ ok: true,
id: 'rabbit',
rev: '1-6e4cb465d49c0368ac3946506d26335d' }
configuring nano to use your database server is as simple as:
var nano = require('nano')('http://localhost:5984')
, db = nano.use('foo')
;
however if you don’t need to instrument database objects you can simply:
// nano parses the url and knows this is a database
var db = require('nano')('http://localhost:5984/foo');
you can also pass options to the require:
// nano parses the url and knows this is a database
var db = require('nano')('http://localhost:5984/foo');
to specify further configuration options you can pass an object literal instead:
// nano parses the url and knows this is a database
var db = require('nano')(
{ "url" : "http://localhost:5984/foo"
, "requestDefaults" : { "proxy" : "http://someproxy" }
, "log" : function (id, args) {
console.log(id, args);
}
});
Please check request for more information on the defaults. They support features like cookie jar, proxies, ssl, etc.
You can tell nano to not parse the url (maybe the server is behind a proxy, is accessed through a rewrite rule or other):
// nano does not parse the url and return the server api
// "http://localhost:5984/prefix" is the CouchDB server root
var couch = require('nano')(
{ "url" : "http://localhost:5984/prefix"
"parseUrl" : false
});
var db = couch.use('foo');
pool size and open sockets
a very important configuration parameter if you have a high traffic website and are using nano is setting up the pool.size. by default, the node.js http global agent (client) has a certain size of active connections that can run simultaneously, while others are kept in a queue. pooling can be disabled by setting the agent property in requestDefaults to false, or adjust the global pool size using:
http.globalAgent.maxSockets = 20;
you can also increase the size in your calling context using requestDefaults if this is problematic. refer to the request documentation and examples for further clarification.
here’s an example explicitly using the keep alive agent (installed using npm install agentkeepalive), especially useful to limit your open sockets when doing high-volume access to couchdb on localhost:
var agentkeepalive = require('agentkeepalive');
var myagent = new agentkeepalive({
maxSockets: 50
, maxKeepAliveRequests: 0
, maxKeepAliveTime: 30000
});
var db = require('nano')(
{ "url" : "http://localhost:5984/foo"
, "requestDefaults" : { "agent" : myagent }
});
database functions
nano.db.create(name, [callback])
creates a couchdb database with the given name.
nano.db.create('alice', function(err, body) {
if (!err) {
console.log('database alice created!');
}
});
nano.db.get(name, [callback])
get informations about name.
nano.db.get('alice', function(err, body) {
if (!err) {
console.log(body);
}
});
nano.db.destroy(name, [callback])
destroys name.
nano.db.destroy('alice');
even though this examples looks sync it is an async function.
nano.db.list([callback])
lists all the databases in couchdb
nano.db.list(function(err, body) {
// body is an array
body.forEach(function(db) {
console.log(db);
});
});
nano.db.compact(name, [designname], [callback])
compacts name, if designname is specified also compacts its
views.
opts.multipart – array of objects for multipart request
nano.relax(opts, [callback])
alias for nano.request
nano.dinosaur(opts, [callback])
alias for nano.request
_
/ '_) WAT U SAY!
_.----._/ /
/ /
_/ ( | ( |
/__.-|_|--|_l
nano.config
an object containing the nano configurations, possible keys are:
url - the couchdb url
db - the database name
nano.updates([params], [callback])
listen to db updates, the available params are:
params.feed – Type of feed. Can be one of
longpoll: Closes the connection after the first event.
continuous: Send a line of JSON per event. Keeps the socket open until timeout.
eventsource: Like, continuous, but sends the events in EventSource format.
params.timeout – Number of seconds until CouchDB closes the connection. Default is 60.
params.heartbeat – Whether CouchDB will send a newline character (\n) on timeout. Default is true.
nano.followUpdates([params], [callback])
** changed in version 6 **
Use Follow to create a solid
_db_updates feed.
Please consult follow documentation for more information as this is a very complete api on it’s own
var feed = nano.followUpdates({since: "now"});
feed.on('change', function (change) {
console.log("change: ", change);
});
feed.follow();
process.nextTick(function () {
nano.db.create('alice');
});
document functions
db.insert(doc, [params], [callback])
inserts doc in the database with optional params. if params is a string, its assumed as the intended document name. if params is an object, its passed as query string parameters and docName is checked for defining the document name.
var alice = nano.use('alice');
alice.insert({ crazy: true }, 'rabbit', function(err, body) {
if (!err)
console.log(body);
});
The insert function can also be used with the method signature db.insert(doc,[callback]), where the doc contains the _id field e.g.
var alice = nano.use('alice')
alice.insert({ _id: 'myid', crazy: true }, function(err, body) {
if (!err)
console.log(body)
})
and also used to update an existing document, by including the _rev token in the document being saved:
var alice = nano.use('alice')
alice.insert({ _id: 'myid', _rev: '1-23202479633c2b380f79507a776743d5', crazy: false }, function(err, body) {
if (!err)
console.log(body)
})
db.destroy(docname, rev, [callback])
removes revision rev of docname from couchdb.
alice.destroy('rabbit', '3-66c01cdf99e84c83a9b3fe65b88db8c0', function(err, body) {
if (!err)
console.log(body);
});
db.get(docname, [params], [callback])
gets docname from the database with optional query string
additions params.
bulk fetch of the database documents, docnames are specified as per
couchdb doc.
additional query string params can be specified, include_docs is always set
to true.
db.fetchRevs(docnames, [params], [callback])
** changed in version 6 **
bulk fetch of the revisions of the database documents, docnames are specified as per
couchdb doc.
additional query string params can be specified, this is the same method as fetch but
include_docs is not automatically set to true.
inserts a doc together with attachments and params. if params is a string, its assumed as the intended document name. if params is an object, its passed as query string parameters and docName is checked for defining the document name.
refer to the doc for more details.
attachments must be an array of objects with name, data and content_type properties.
get docname together with its attachments via multipart/related request with optional query string additions
params. refer to the
doc for more details.
the multipart response body is a Buffer.
alice.multipart.get('rabbit', function(err, buffer) {
if (!err)
console.log(buffer.toString());
});
calls a view of the specified design with optional query string additions
params. if you’re looking to filter the view results by key(s) pass an array of keys, e.g
{ keys: ['key1', 'key2', 'key_n'] }, as params.
Note that the data is sent in the body of the request.
An example update handler follows:
"updates": {
"in-place" : "function(doc, req) {
var field = req.body.field;
var value = req.body.value;
var message = 'set '+field+' to '+value;
doc[field] = value;
return [doc, message];
}"
var nano = require('nano')('http://localhost:5984')
, username = 'user'
, userpass = 'pass'
, callback = console.log // this would normally be some callback
, cookies = {} // store cookies, normally redis or something
;
nano.auth(username, userpass, function (err, body, headers) {
if (err) {
return callback(err);
}
if (headers && headers['set-cookie']) {
cookies[user] = headers['set-cookie'];
}
callback(null, "it worked");
});
reusing a cookie:
var auth = "some stored cookie"
, callback = console.log // this would normally be some callback
, alice = require('nano')(
{ url : 'http://localhost:5984/alice', cookie: 'AuthSession=' + auth });
;
alice.insert(doc, function (err, body, headers) {
if (err) {
return callback(err);
}
// change the cookie if couchdb tells us to
if (headers && headers['set-cookie']) {
auth = headers['set-cookie'];
}
callback(null, "it worked");
});
getting current session:
var nano = require('nano')({url: 'http://localhost:5984', cookie: 'AuthSession=' + auth});
nano.session(function(err, session) {
if (err) {
return console.log('oh noes!')
}
console.log('user is %s and has these roles: %j',
session.userCtx.name, session.userCtx.roles);
});
advanced features
extending nano
nano is minimalistic but you can add your own features with
nano.request(opts, callback)
for example, to create a function to retrieve a specific revision of the
rabbit document:
you can pipe in nano like in any other stream.
for example if our rabbit document has an attachment with name picture.png
(with a picture of our white rabbit, of course!) you can pipe it to a writable stream
var fs = require('fs'),
nano = require('nano')('http://127.0.0.1:5984/');
var alice = nano.use('alice');
alice.attachment.get('rabbit', 'picture.png').pipe(fs.createWriteStream('/tmp/rabbit.png'));
then open /tmp/rabbit.png and you will see the rabbit picture.
licensed under the apache license, version 2.0 (the “license”);
you may not use this file except in compliance with the license.
you may obtain a copy of the license at
http://www.apache.org/licenses/LICENSE-2.0.html
unless required by applicable law or agreed to in writing, software
distributed under the license is distributed on an “as is” basis,
without warranties or conditions of any kind, either express or implied.
see the license for the specific language governing permissions and
limitations under the license.
nano
minimalistic couchdb driver for node.js
nanofeatures:nano.installation
npm install nanotable of contents
getting started
to use
nanoyou need to connect it to your couchdb install, to do that:to create a new database:
and to use it:
in this examples we didn’t specify a
callbackfunction, the absence of a callback means “do this, ignore what happens”. innanothe callback function receives always three arguments:err- the error, if anybody- the http response body from couchdb, if no error. json parsed body, binary for non json responsesheader- the http response header from couchdb, if no errora simple but complete example using callbacks is:
if you run this example(after starting couchdb) you will see:
you can also see your document in futon.
configuration
configuring nano to use your database server is as simple as:
however if you don’t need to instrument database objects you can simply:
you can also pass options to the require:
to specify further configuration options you can pass an object literal instead:
Please check request for more information on the defaults. They support features like cookie jar, proxies, ssl, etc.
You can tell nano to not parse the url (maybe the server is behind a proxy, is accessed through a rewrite rule or other):
pool size and open sockets
a very important configuration parameter if you have a high traffic website and are using nano is setting up the
pool.size. by default, the node.js http global agent (client) has a certain size of active connections that can run simultaneously, while others are kept in a queue. pooling can be disabled by setting theagentproperty inrequestDefaultsto false, or adjust the global pool size using:you can also increase the size in your calling context using
requestDefaultsif this is problematic. refer to the request documentation and examples for further clarification.here’s an example explicitly using the keep alive agent (installed using
npm install agentkeepalive), especially useful to limit your open sockets when doing high-volume access to couchdb on localhost:database functions
nano.db.create(name, [callback])
creates a couchdb database with the given
name.nano.db.get(name, [callback])
get informations about
name.nano.db.destroy(name, [callback])
destroys
name.even though this examples looks sync it is an async function.
nano.db.list([callback])
lists all the databases in couchdb
nano.db.compact(name, [designname], [callback])
compacts
name, ifdesignnameis specified also compacts its views.nano.db.replicate(source, target, [opts], [callback])
replicates
sourceontargetwith optionsopts.targethas to exist, addcreate_target:truetooptsto create it prior to replication.nano.db.changes(name, [params], [callback])
asks for the changes feed of
name,paramscontains additions to the query string.nano.db.follow(name, [params], [callback])
Uses Follow to create a solid changes feed. please consult follow documentation for more information as this is a very complete API on it’s own.
nano.db.info([callback])
gets database information.
nano.db.info(function(err, body) { if (!err) { console.log(‘got database info’’, body); } });
nano.use(name)
creates a scope where you operate inside
name.nano.db.use(name)
alias for
nano.usenano.db.scope(name)
alias for
nano.usenano.scope(name)
alias for
nano.usenano.request(opts, [callback])
makes a request to couchdb, the available
optsare:opts.db– the database nameopts.method– the http method, defaults togetopts.path– the full path of the request, overridesopts.docandopts.attopts.doc– the document nameopts.att– the attachment nameopts.qs– query string parameters, appended after any existingopts.path,opts.doc, oropts.attopts.content_type– the content type of the request, default tojsonopts.headers– additional http headers, overrides existing onesopts.body– the document or attachment bodyopts.encoding– the encoding for attachmentsopts.multipart– array of objects for multipart requestnano.relax(opts, [callback])
alias for
nano.requestnano.dinosaur(opts, [callback])
alias for
nano.requestnano.config
an object containing the nano configurations, possible keys are:
url- the couchdb urldb- the database namenano.updates([params], [callback])
listen to db updates, the available
paramsare:params.feed– Type of feed. Can be one oflongpoll: Closes the connection after the first event.continuous: Send a line of JSON per event. Keeps the socket open until timeout.eventsource: Like, continuous, but sends the events in EventSource format.params.timeout– Number of seconds until CouchDB closes the connection. Default is 60.params.heartbeat– Whether CouchDB will send a newline character (\n) on timeout. Default is true.nano.followUpdates([params], [callback])
** changed in version 6 **
Use Follow to create a solid
_db_updatesfeed. Please consult follow documentation for more information as this is a very complete api on it’s owndocument functions
db.insert(doc, [params], [callback])
inserts
docin the database with optionalparams. if params is a string, its assumed as the intended document name. if params is an object, its passed as query string parameters anddocNameis checked for defining the document name.The
insertfunction can also be used with the method signaturedb.insert(doc,[callback]), where thedoccontains the_idfield e.g.and also used to update an existing document, by including the
_revtoken in the document being saved:db.destroy(docname, rev, [callback])
removes revision
revofdocnamefrom couchdb.db.get(docname, [params], [callback])
gets
docnamefrom the database with optional query string additionsparams.db.head(docname, [callback])
same as
getbut lightweight version that returns headers only.db.copy(src_doc, dest_doc, opts, [callback])
copythe contents (and attachments) of a document to a new document, or overwrite an existing target documentdb.bulk(docs, [params], [callback])
bulk operations(update/delete/insert) on the database, refer to the couchdb doc.
db.list([params], [callback])
list all the docs in the database with optional query string additions
params. This is useful for searching.For a full list of params, see couchdb doc.
db.fetch(docnames, [params], [callback])
bulk fetch of the database documents,
docnamesare specified as per couchdb doc. additional query stringparamscan be specified,include_docsis always set totrue.db.fetchRevs(docnames, [params], [callback])
** changed in version 6 **
bulk fetch of the revisions of the database documents,
docnamesare specified as per couchdb doc. additional query stringparamscan be specified, this is the same method as fetch butinclude_docsis not automatically set totrue.multipart functions
db.multipart.insert(doc, attachments, params, [callback])
inserts a
doctogether withattachmentsandparams. if params is a string, its assumed as the intended document name. if params is an object, its passed as query string parameters anddocNameis checked for defining the document name. refer to the doc for more details.attachmentsmust be an array of objects withname,dataandcontent_typeproperties.db.multipart.get(docname, [params], [callback])
get
docnametogether with its attachments viamultipart/relatedrequest with optional query string additionsparams. refer to the doc for more details. the multipart response body is aBuffer.attachments functions
db.attachment.insert(docname, attname, att, contenttype, [params], [callback])
inserts an attachment
attnametodocname, in most casesparams.revis required. refer to the doc for more details.or using
pipe:db.attachment.get(docname, attname, [params], [callback])
get
docname‘s attachmentattnamewith optional query string additionsparams.or using
pipe:db.attachment.destroy(docname, attname, [params], [callback])
changed in version 6
destroy attachment
attnameofdocname‘s revisionrev.views and design functions
db.view(designname, viewname, [params], [callback])
calls a view of the specified design with optional query string additions
params. if you’re looking to filter the view results by key(s) pass an array of keys, e.g{ keys: ['key1', 'key2', 'key_n'] }, asparams.db.viewWithList(designname, viewname, listname, [params], [callback])
calls a list function feeded by the given view of the specified design document.
db.show(designname, showname, doc_id, [params], [callback])
calls a show function of the specified design for the document specified by doc_id with optional query string additions
params.take a look at the couchdb wiki for possible query paramaters and more information on show functions.
db.atomic(designname, updatename, docname, [body], [callback])
calls the design’s update function with the specified doc in input.
Note that the data is sent in the body of the request. An example update handler follows:
db.search(designname, searchname, [params], [callback])
calls a view of the specified design with optional query string additions
params.check out the tests for a fully functioning example.
using cookie authentication
nano supports making requests using couchdb’s cookie authentication functionality. there’s a example in coffeescript, but essentially you just:
reusing a cookie:
getting current session:
advanced features
extending nano
nano is minimalistic but you can add your own features with
nano.request(opts, callback)for example, to create a function to retrieve a specific revision of the
rabbitdocument:pipes
you can pipe in nano like in any other stream. for example if our
rabbitdocument has an attachment with namepicture.png(with a picture of our white rabbit, of course!) you can pipe it to awritable streamthen open
/tmp/rabbit.pngand you will see the rabbit picture.tutorials, examples in the wild & screencasts
roadmap
check issues
tests
to run (and configure) the test suite simply:
after adding a new test you can run it individually (with verbose output) using:
where
list_doc_paramsis the test name.meta
git clone git://github.com/dscape/nano.git(oo)--',-in caoslicense
copyright 2011 nuno job <nunojob.com> (oo)–’,–
licensed under the apache license, version 2.0 (the “license”); you may not use this file except in compliance with the license. you may obtain a copy of the license at
unless required by applicable law or agreed to in writing, software distributed under the license is distributed on an “as is” basis, without warranties or conditions of any kind, either express or implied. see the license for the specific language governing permissions and limitations under the license.