Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added reduce-sort for Riak

  • Loading branch information...
commit 9481a4cb268504d8fe88583e7acd24d8e5f1b403 1 parent bc84bd8
mde authored
View
4 README.md
@@ -189,7 +189,7 @@ Here are some more examples of queries:
```javascript
// Where "foo" is 'BAR' and "bar" is not null
{foo: 'BAR', bar: {ne: null}}
-// Where "foo" begins with 'B' (SQL-adapter only)
+// Where "foo" begins with 'B'
{foo: {'like': 'B'}}
// Where foo is less than 2112, and bar is 'BAZ'
{foo: {lt: 2112}, bar: 'BAZ'}
@@ -205,7 +205,7 @@ gt: greater than
lt: less than
gte: greater than or equal
lte: less than or equal
-like: like (SQL adapters only)
+like: like
A simple string-value for a query parameter is the same as 'eql'. `{foo: 'bar'}`
is the same as `{foo: {eql: 'bar'}}`.
View
72 lib/adapters/riak/index.js
@@ -5,6 +5,7 @@ var utils = require('utilities')
, request = utils.request
, BaseAdapter = require('../base_adapter').BaseAdapter
, _baseConfig
+ , _reduceFunction
, _mapReduceQuery
, _bucketizeModelName;
@@ -36,11 +37,68 @@ _bucketizeModelName = function (name) {
return bucketName;
};
-_mapReduceQuery = function (bucket, conditions) {
+// This function is special -- its source is transformed into
+// a JSON-safe string and posted as the reduce-sort to Riak
+_reduceFunction = function (values, arg) {
+ // Dummy value to replace with real sort data -- will look
+ // like {'foo': 'asc', 'bar': 'desc'}
+ var sort = '__sort__'
+ // Directional sort, returns explicit zero if equal
+ , baseSort = function (a, b, dir) {
+ if (a == b) {
+ return 0;
+ }
+ if (dir == 'asc') {
+ return a > b ? 1 : -1;
+ }
+ else {
+ return a > b ? -1 : 1;
+ }
+ }
+ // Iterates each of the sort columns until it finds a
+ // pair of values that are not the same
+ , columnSort = function (a, b) {
+ var ret;
+ for (var p in sort) {
+ // Call the directional sort for the two values
+ // in this property
+ ret = baseSort(a[p], b[p], sort[p]);
+ // -1 and 1 are truthy
+ if (ret) {
+ return ret;
+ }
+ }
+ return 1;
+ };
+ return values.sort(columnSort);
+};
+
+_mapReduceQuery = function (bucket, conditions, sort) {
+ var reduce = ''
+ , reduceSource;
+
+ // If there's any sort, create the reduce stage for sorting
+ // 1. The function-source is POSTed as JSON, so transform the
+ // function-source into a JSON-safe string
+ // 2. Insert the actual sort info, replace the dummy __sort__
+ if (sort) {
+ reduceSource = _reduceFunction.toString() // Get the function source
+ // Strip comments
+ .replace(/\/\/.*(\n)/g, '')
+ // Strip linebreaks
+ .replace(/\n/g, ' ')
+ // Reduce multiple spaces to single space
+ .replace(/ {2,}/g, ' ')
+ // Replace placeholder with real sort, e.g., {'foo': 'asc'}
+ .replace('\'__sort__\'', sort);
+ reduce = ', {"reduce": {"language": "javascript", "source": "' +
+ reduceSource + '"}}';
+ }
+
return '{"inputs": "' + bucket + '", "query": [{"map": {"language": '+
'"javascript","source": "function (value, keyData, arg) { ' +
'var data = Riak.mapValuesJson(value)[0]; if ' + conditions +
- ' { return [data]; } else { return []; } }"}}]}';
+ ' { return [data]; } else { return []; } }"}}' + reduce + ']}';
};
utils.mixin(Adapter.prototype, new (function () {
@@ -50,6 +108,10 @@ utils.mixin(Adapter.prototype, new (function () {
, 'or': '||'
};
+ this._serializeSortOrder = function (sort) {
+ return sort ? JSON.stringify(sort).replace(/"/g, "'") : '';
+ };
+
this._serializeConditions = function (conditions) {
var cond = this._serializeOperation(conditions);
return cond;
@@ -155,7 +217,8 @@ utils.mixin(Adapter.prototype, new (function () {
var bucket = _bucketizeModelName(query.model.modelName)
, id = query.byId
, requestOpts
- , conditions;
+ , conditions
+ , sort;
// Single instance-lookup by id
if (id) {
@@ -191,10 +254,11 @@ utils.mixin(Adapter.prototype, new (function () {
// Teh mapreducy
else {
conditions = this._serializeConditions(query.conditions);
+ sort = this._serializeSortOrder(query.opts.sort);
requestOpts = {
url: '/mapred'
, method: 'POST'
- , data: _mapReduceQuery(bucket, conditions)
+ , data: _mapReduceQuery(bucket, conditions, sort)
};
this.request(requestOpts, function (err, data) {
var rows
View
12 test/adapters/riak/index.js
@@ -139,6 +139,18 @@ tests = {
});
}
+/*
+, 'test all, by map-reduce, equality': function (next) {
+ Zooby.all({foo: 'FOO'}, {sort: {createdAt: 'desc'}}, function (err, data) {
+ if (err) {
+ throw err;
+ }
+ assert.ok(data.length > 0);
+ assert.equal(data[0].id, currentId);
+ next();
+ });
+ }
+*/
};
module.exports = tests;
Please sign in to comment.
Something went wrong with that request. Please try again.