Skip to content

Commit

Permalink
adding support for comparators and conditional queries. Closes #1. Cl…
Browse files Browse the repository at this point in the history
…oses #2.
  • Loading branch information
ekryski committed Oct 26, 2015
1 parent b585f72 commit 5a3d298
Show file tree
Hide file tree
Showing 3 changed files with 283 additions and 80 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"dependencies": {
"feathers-errors": "^0.2.5",
"feathers-query-filters": "^1.1.1",
"is-plain-object": "^2.0.1",
"knex": "^0.8.6",
"uberproto": "^1.1.2"
},
Expand Down
65 changes: 59 additions & 6 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import Proto from 'uberproto';
import filter from 'feathers-query-filters';
import isPlainObject from 'is-plain-object';
import knex from 'knex';
import { types as errors } from 'feathers-errors';

const METHODS = {
$or: 'orWhere',
$not: 'whereNot',
$in: 'whereIn',
$nin: 'whereNotIn'
};

const OPERATORS = {
$lt: '<',
$lte: '<=',
$gt: '>',
$gte: '>='
};

// Create the service.
export const Service = Proto.extend({
init(name, options) {
Expand All @@ -25,6 +40,35 @@ export const Service = Proto.extend({
return this.knex(this.name);
},

knexify(query, params, parentKey) {
Object.keys(params).forEach((key) => {
const value = params[key];

if (isPlainObject(value)) {
return this.knexify(query, value, key);
}

const column = parentKey || key;
const method = METHODS[key];
const operator = OPERATORS[key] || '=';

// TODO (EK): Handle $or queries with nested specials.
// Right now they won't work and we'd need to start diving
// into nested where conditions.
if (method) {
if (key === '$or') {
return value.forEach(condition => {
query[method].call(query, condition);
});
}

return query[method].call(query, column, value);
}

return query.where(column, operator, value);
});
},

find(params, callback) {
let fields = ['*'];
let query = this.db().select(fields);
Expand All @@ -38,7 +82,10 @@ export const Service = Proto.extend({
fields = filters.$select;
}

query = this.db().select(... fields).where(params.query);
query = this.db().select(... fields);

// build up the kinex query out of the query params
this.knexify(query, params.query);

// Handle $sort
if (filters.$sort) {
Expand Down Expand Up @@ -84,15 +131,21 @@ export const Service = Proto.extend({

create(data, params, callback) {
this.db().insert(data).then(rows => {
// if we inserted a single record call get otherwise call find
// NOTE (EK): If we inserted a single record or we inserted multiple but we
// are not using a Postgres DB call .get() to return the newly
// inserted record.
if (rows.length === 1) {
return this.get(rows[0], params, callback);
}

// TODO (EK): We'll need to use a .orWhere query for each id that we pass
// So we need to figure out what the syntax should be for find to handle
// OR queries. Possibly $or as a special param.
this.find(rows[0], params, callback);
// NOTE (EK): If we are using PG then it will return the ids
// of the inserted records so we have to build up an
// $or query to return these newly inserted records.
var query = {
$or: rows.map(row => { return { id: row[0] }; })
};

this.find(query, params, callback);
}, callback);
},

Expand Down
Loading

0 comments on commit 5a3d298

Please sign in to comment.