nano-records
v1.1.2
Published
Utility returns objects for interacting with CouchDB.
Downloads
9
Readme
Nano Records
A module for interacting with CouchDB through nano with Nodejs.
Conflicts are avoided with automated retries, errors are sanitised, designs are persisted on an as-needed basis, and so on. Intended to make life simpler by abstracting away some general database busywork and hopefully makes it easy to get up and running.
Notice
If you are using CouchDB2.0/Cloudant this library nano-records
has been superceded by Couch Recliner.
Upgrading from 1.0.9 to 1.1.0
db.doc.forcedWrite
is nowdb.doc.write
db.doc.write
has been removeddb.doc.forcedUpdate
is nowdb.doc.updateOrWrite
db.designs.show
is nowdb.show.catalog
db.designs.view
is nowdb.view.catalog
Install
npm install nano --save
npm install nano-records --save
var nano = require('nano')("localhost");
var NanoRecords = require('nano-records');
var dbName = "my-database";
var db = new NanoRecords(nano, dbName);
// typescript
import NanoRecords = require('nano-records');
Each NanoRecords instance represents one database.
Provide NanoRecords with a running instance of nano and a chosen database name. This should be all you need to get started.
Documents
db.doc.create(body, (err, doc) => {
if (err)
return;
// doc is a NanoRecords document
console.log(doc.body);
});
Easiest way to persist a new record, returns a NanoRecords document, the _id
attribute is generated by CouchDB.
doc.read((err) => {
if (!err)
console.log('success!');
});
db.doc.read(id, (err, doc) => {
if (err)
return;
// doc is a NanoRecords document
console.log(doc.body);
});
Retrieve the latest version of the body of a document.
doc.write(body, (err) => {
if (!err)
console.log('success!');
});
db.doc.write(id, body, (err, doc) => {
if (err)
return;
// doc is a NanoRecords document
console.log(doc.body);
});
Overwrite an existing document or create a new document if one doesn't exist.
doc.update(body, (err) => {
if (!err)
console.log('success!');
});
db.doc.update(id, body, (err, doc) => {
if (err)
return;
// doc is a NanoRecords document
console.log(doc.body);
});
Deeply extend an existing document.
db.doc.updateOrWrite(id, body, (err, doc) => {
if (err)
return;
// doc is a NanoRecords document
console.log(doc.body);
});
Deeply extend an existing document or create a document if one doesn't exist.
doc.destroy((err) => {
if (!err)
console.log('success!');
});
db.doc.destroy(id, (err) => {
if (!err)
console.log('success!');
});
Remove a document.
doc.head((err, rev, result) => {
if (err)
return;
// rev is the most up to date document revision
console.log(result);
});
db.doc.head(id, (err, rev, result) => {
if (err)
return;
// rev is the most up to date document revision
console.log(result);
});
Retrieve header information.
doc.getId() == doc.body['_id']; // true
doc.getRev() == doc.body['_rev']; // true
doc.getBody(); // {}
Access the document body's _id
and _rev
properties. Another way of writing doc.body['_id']
and doc.body['_rev']
.
Create a deep clone of the full document body deepExtend({}, doc.body)
1.
Attachments
doc.attachment.read(name, (err, data) => {
if (err)
return;
console.log(data.length);
});
db.doc.attachment.read(id, name, (err, data) => {
if (err)
return;
console.log(data.length);
});
Read an attachment.
doc.attachment.write(name, data, mimeType, (err) => {
if (!err)
console.log('success!');
});
db.doc.attachment.write(id, name, data, mimeType, (err) => {
if (!err)
console.log('success!');
});
Overwrite an existing attachment with the same name or create a new attachment if one doesn't exist.
doc.attachment.destroy(name, (err) => {
if (!err)
console.log('success!');
});
db.doc.attachment.destroy(id, name, (err) => {
if (!err)
console.log('success!');
});
Remove an attachment.
doc.attachment.list();
doc.attachment.exists(name);
Return attachment names as an array and whether a specific attachment exists.
Attachment streams
doc.attachment.createReadStream(name, (err) => {
if (!err)
console.log('success!');
}).pipe(fs.createWriteStream('./my-file.txt'));
db.doc.attachment.createReadStream(id, name, (err) => {
if (!err)
console.log('success!');
}).pipe(fs.createWriteStream('./my-file.txt'));
Read the attachment as a stream.
var reader = fs.createReadStream('./my-file.txt');
reader.pipe(doc.attachment.createWriteStream(name, mimeType, (err) => {
if (!err)
console.log('success!');
}));
Write an attachment using a stream. It's important to note that streams cannot be retried, if there is an error you will have to pipe a new stream manually.
Designs
// > ./designs.json
{
"foo": {
"views": {
"comments": {
"map": "function (doc) { ... };",
"reduce": "function (keys, values, rereduce) { ... };"
}
},
"shows": {
"post": "function (doc, req) { ... };"
}
},
"bar": {
"language": "javascript",
"views": {}
}
}
var designs = require('./designs.json');
var db = new NanoRecords(nano, dbName, designs);
When creating your NanoRecords instance optionally provide it a catalog of designs to use. You can learn more about Views and Design Documents on the CouchDB website.
db.show.catalog(id, design, name, (err, result) => {
if (err)
return;
console.log(result);
});
Persist a show using the provided design (ie. "foo"
) and name (ie. "post"
) if it's not already there, then return the result for the doc.
db.view.catalog(design, name, params, (err, list) => {
if (err)
return;
// list is a NanoRecords list
console.log(list.values());
});
Persist a view similar to db.show.catalog
and return the result. An empty list object is returned if there is an error.
View helpers
db.view.all(keys, params, (err, list) => {
if (err)
return;
// list is a NanoRecords list
console.log(list.values());
});
Will generate a view for you using the provided keys, which returns a list of documents.
Useful for simple search functions, for example keys
may be "user_id"
then you can provide { key: "myuserid" }
to params
and find relevant results. The keys
parameter may also be an array of values, or nested values. It's best not to provide parameters to this function which are dynamic in nature, as a new view is persisted to the database for each set of keys provided.
Complex views are still best constructed manually. Read more about view helpers on: CouchDB design documents using view helpers in nano-records.
db.view.only(keys, values, params, (err, list) => {
if (err)
return;
// list is a NanoRecords list
console.log(list.values());
});
Will generate a view similar to view.all
which only returns a specific set of values from each document. For example ["created_at", "title", "author.name"]
would return { created_at: "mydate", title: "mytitle", author: { name: "myauthorname" } }
as each result.
This is more efficient than performing a full document lookup.
Lists
list.total; // 11
list.offset; // 0
list.rows; // raw result
list.ids(); // [ids...]
list.keys(); // [keys...]
list.values(); // [values...]
list.docs(); // [NanoRecords documents...]
list.doc(index); // NanoRecords document
The list.docs
method may not give you complete document objects depending on the values that were returned by the view. However running doc.read
will fetch the full document from the database, similarly all normal NanoRecords document functions should work as you expect.
A common way to get just the first document is list.doc(0)
.
Db
db.create((err) => {
if (!err)
console.log('success!');
});
You should never need to but it is there if you want to use it.
db.destroy("_DESTROY_", (err) => {
if (!err)
console.log('success!');
});
Destroy the database, first parameter must be _DESTROY_
.
db.reset("_RESET_", (err) => {
if (!err)
console.log('success!');
});
Destroy and then recreate the database, first parameter must be _RESET_
.
Errors
err.scope; // source of the error
err.name; // error code
err.message; // more information
err.raw; // the full error returned from nano
// common errors
// ==
// not_found: Not found.
// missing_id: Id parameter required.
// conflict: There was a conflict.
// malformed_script: Problem with one of your designs.
// no_db_file: Database missing.
When an error is returned it has the above format. Generally you should never see no_db_file
or conflict
so maybe these are not so common errors.
A conflict
would only happen if the max number of retries was reached on a request, possibly you have too much activity on a single document.
You might see no_db_file
if your CouchDB has security locked down.
Contribute
If you like what you see please feel encouraged to get involved report problems and submit pull requests! As of the time of this writing the project is new with one maintainer.
New repository under development: couch-recliner