Skip to content

Commit

Permalink
Complex OR and AND conditions in filters
Browse files Browse the repository at this point in the history
  • Loading branch information
EugeneKostrikov committed Jul 9, 2014
1 parent 3221cc2 commit 5c97137
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 4 deletions.
13 changes: 13 additions & 0 deletions lib/adapters/mongodb.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ adapter.findMany = function(model, query, projection) {

var pk = model.pk || "_id";

function parseQuery(query){

_.each(query, function(val, key){
var m;
if(model.schema.tree[key] === Date && _.isString(val)){
Expand Down Expand Up @@ -300,9 +302,13 @@ adapter.findMany = function(model, query, projection) {
$regex: val.regex ? val.regex : '',
$options: val.options ? val.options : ''
};
}else if(key === 'or' || key === 'and'){
query['$' + key] = _.map(val, parseQuery);
delete query[key];
}
});


if(_.isObject(query)){
if(_.isArray(query)) {
if(query.length) dbQuery[pk] = {$in: query};
Expand All @@ -316,6 +322,13 @@ adapter.findMany = function(model, query, projection) {
delete dbQuery.id;
}
}
}

return dbQuery;
}

if (_.isObject(query)){
query = parseQuery(query);
}else if(typeof query === 'number' && arguments.length === 2){
//Just for possible backward compatibility issues
projection = projection || {};
Expand Down
2 changes: 1 addition & 1 deletion lib/fortune.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ Fortune.prototype.resource = function(name, schema, options, schemaCallback) {
* @return {Object}
*/
Fortune.prototype._preprocessSchema = function (schema) {
['id', 'href', 'links', 'in'].forEach(function (reservedKey) {
['id', 'href', 'links', 'in', 'or', 'and'].forEach(function (reservedKey) {
if (schema.hasOwnProperty(reservedKey)) {
delete schema[reservedKey];
console.warn('Reserved key "' + reservedKey + '" is not allowed.');
Expand Down
14 changes: 11 additions & 3 deletions lib/querytree.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,17 @@ function parseQuery(query, requestedResource){
//String ref
freeze[key] = createSubrequest(q, schemaBranch);
}else{
//Plain field
//Do nothing. fetchIds should have this untouched
freeze[key] = q;
if (key === 'or' || key === 'and' || key === '$and' || key === '$or'){
freeze[key] = RSVP.all(_.map(q, function(subq){
return exports.parse(requestedResource, subq).then(function(result){
return result;
});
}));
}else{
//Plain field
//Do nothing. fetchIds should have this untouched
freeze[key] = q;
}
}
});
return RSVP.hash(freeze);
Expand Down
58 changes: 58 additions & 0 deletions test/fortune/fields_and_filters.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,28 @@ module.exports = function(options){
done();
});
});
it('should support or query', function(done){
request(baseUrl).get('/people?filter[or][0][name]=Dilbert&filter[or][1][email]=robert@mailbert.com&sort=name')
.expect(200)
.end(function(err, res){
should.not.exist(err);
var body = JSON.parse(res.text);
(body.people.length).should.equal(2);
(body.people[0].name).should.equal('Dilbert');
(body.people[1].name).should.equal('Robert');
done();
});
});
it('should have id filter', function(done){
request(baseUrl).get('/cars?filter[id]=' + ids.cars[0])
.expect(200)
.end(function(err, res){
should.not.exist(err);
var body = JSON.parse(res.text);
(body.cars[0].id).should.equal(ids.cars[0]);
done();
});
});
describe('filtering by related objects fields', function(){
beforeEach(function(done){
neighbourhood(adapter, ids).then(function(){
Expand Down Expand Up @@ -362,6 +384,42 @@ module.exports = function(options){
});
});
});
it('should be able to apply OR filter to related resources', function(done){
request(baseUrl).get('/cars?filter[or][0][owner][soulmate]=' + ids.people[0] + '&filter[or][1][id]=' + ids.cars[0])
.expect(200)
.end(function(err, res){
should.not.exist(err);
var body = JSON.parse(res.text);
(body.cars.length).should.equal(2);
var one = _.findWhere(body.cars, {id: ids.cars[0]});
var two = _.findWhere(body.cars, {id: ids.cars[1]});
should.exist(one);
should.exist(two);
done();
});
});
it('should be able to apply AND filter to related resources', function(done){
request(baseUrl).get('/pets?filter[and][0][owner][soulmate][email]=' + ids.people[0] + '&filter[and][1][owner][email]=' + ids.people[1])
.expect(200)
.end(function(err, res){
should.not.exist(err);
var body = JSON.parse(res.text);
(body.pets.length).should.equal(1);
(body.pets[0].id).should.equal(ids.pets[0]);
done();
})
});
it('should be able to nest OR and AND filters', function(done){
request(baseUrl).get('/houses?filter[or][0][and][0][owners][in]=' + ids.people[0])
.expect(200)
.end(function(err, res){
should.not.exist(err);
var body = JSON.parse(res.text);
(body.houses.length).should.equal(1);
(body.houses[0].id).should.equal(ids.houses[0]);
done();
})
});
});
});

Expand Down

0 comments on commit 5c97137

Please sign in to comment.