Fork me on GitHub

riak-js

Extensible Javascript library for accessing Riak, with
an implementation for node.js via HTTP.

The jQuery client is on the verge of being dropped. It is becoming difficult to maintain and I stopped using it. Contact me and try to convince me why we should keep it. Basho provides one, anyway.
db.save('airlines', 'KLM', {fleet: 111, alliance: 'SkyTeam'}, { links:
  [{ bucket: 'flights', key: 'KLM-8098', tag: 'cargo' },
   { bucket: 'flights', key: 'KLM-1196', tag: 'passenger' }]
})()

db.getAll('flights', { where: { ready: true }})()  // Riak 0.12+

node.js setup

// npm install riak-js  # @latest or @stable -- your pick
var db = require('riak-js').getClient()

// git clone git://github.com/frank06/riak-js.git  # or cloning the repo
var db = require('/path/to/riak-js/lib').getClient()

jQuery (browser) setup

<script type="text/javascript" src="riak.js"></script>
<script type="text/javascript" src="riak-jquery.js"></script>

var db = new Riak();

Guide by example

db.get('flights', 'KLM-5034')(function(flight, meta) {
  flight.status = 'delayed'
  db.save('flights', 'KLM-5034', flight)()
});

Here we introduce the callback mechanism, and the meta variable, that contains associated information to the retrieved document and the response.

Operations always return a function whose only parameter is a function. This is where we provide our callback — but we're not obliged to do so. It gives us back the document as the first parameter, and meta as the second.

Things do go wrong, unfortunately, and so if we want to check for errors we do if (db.error(flight)) (with flight's type being Error). This gets returned whenever there's a client error, or when the server returns an HTTP status >= 400.

The meta object could look something like:

{ headers: 
   { 'x-riak-vclock': 'a85hYGBgymDKBVIsZlzOrhlMiYx5rAwPJu04ygcVtrBxLwIKMwOFFWcAhbMA'
   , vary: 'Accept-Encoding'
   , server: 'MochiWeb/1.1 WebMachine/1.6.1 (eat around the stinger)'
   , link: '< /riak/crew/3428432407>; riaktag="_", < /riak/crew/4428132499>; riaktag="_", < /riak/users>; rel="up"'
   , 'last-modified': 'Mon, 19 Jul 2010 09:34:25 GMT'
   , etag: '6LnqO9nVDyCxvCIJk0QdUO'
   , date: 'Mon, 19 Jul 2010 20:54:42 GMT'
   , 'content-type': 'application/json'
   , 'content-length': '511'
   }
, key: 'KLM-5034'
, statusCode: 200
, type: 'application/json'
}

It also contains handy methods to deal with links, and shortcuts to certain headers.

Options

riak-js aims to ship sensible defaults, which can of course be overriden. Using mixins behind the scenes means we only have to supply the properties to override. This can be done during client instantiation, so that it applies to all requests:

var db = require('riak-js').getClient({ host: '192.168.1.109', port: 9000, interface: 'backup', debug: false })

But also tune them per-request. An example below saving an image:

fs.readFile("drunk-pilot.png", 'binary', function (err, image) {
  if (err) throw err;
  db.save('evidence', 'pilot-smith-drunk', image, { type: 'jpeg', headers: { 'X-Whatever-Header': 'fire' } })()
});

And the defaults are:

{
  clientId: 'riak-js', 
  interface: 'riak',
  headers: {},
  debug: true,
  callback: function(response, meta) {
    if (response)
      Riak.prototype.log(meta.type == 'application/json' ? JSON.stringify(response) : response)
  }
}

Which means that if you don't provide a callback, the result will be logged to stdout. Note that you cannot change host or port once the client is instantiated.

Map/Reduce API

db.map({name: 'Riak.mapValuesJson'}).run('albums')()

You can chain any number of phases or pass arrays, too:

db
  .link({ bucket: 'flights', keep: false })
  .map('Riak.mapValuesJson')
  .reduce(['Riak.filterNotFound', function(value, count) { return value.slice(0, count - 1) }])
  .run('airlines')(function(flights) {
    sys.puts(flights)
  })

Good to know

Check out the tests for more examples of API usage.

Authors and contributors, in order of appearence