Skip to content

Commit

Permalink
Support for $exists, ?foo or ?!foo/
Browse files Browse the repository at this point in the history
  • Loading branch information
richardschneider committed Jan 25, 2016
1 parent e847944 commit c72934c
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 9 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,8 @@ Any query parameters other then _fields_, _omit_, _sort_, _offset_, and _limit_
* Multiple not-equals comparisons are merged into a `$nin` operator. For example, `id!=a&id!=b` yields `{id:{$nin:['a','b']}}`.
* Comma separated values in equals or not-equals yeild an `$in` or `$nin` operator. For example, `id=a,b` yields `{id:{$in:['a','b']}}`.
* Regex patterns. For example, `name=/^john/i` yields `{id: /^john/i}`.
* Parameters without a value check that the field is present. For example, `foo&bar=10` yields `{foo: {$exists: true}, bar: 10}`.
* Parameters prefixed with a _not_ (!) and without a value check that the field is not present. For example, `!foo&bar=10` yields `{foo: {$exists: false}, bar: 10}`.

### A note on embedded documents
Comparisons on embedded documents should use mongo's [dot notation](http://docs.mongodb.org/manual/reference/glossary/#term-dot-notation) instead of express's 'extended' [query parser](https://www.npmjs.com/package/qs) (Use `foo.bar=value` instead of `foo[bar]=value`).
Expand All @@ -143,6 +145,4 @@ npm test
```

## Todo
* Add support for `$exists`. Arguments w/o a value (ie., `foo&bar=10`) would yield `{'foo':{$exists:true}, 'bar':...}`; prefixed with not(!) (ie., `!foo&bar=10`) would yield `{'foo': {$exists: false}, 'bar': ...}`.
* Add support for `$regex`. Values with slashes (field=/pattern/) would result in `{'field':{$regex: /pattern/}}`. Don't forget case-insensitive patterns (/pattern/i).
* Add support for forced string comparison; value in quotes (`field='10'`) would force a string compare. Should allow for string with embedded comma (`field='a,b'`).
24 changes: 18 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,24 @@ function typedValue(value) {
// for example:
// + f('key','value') => {key:'key',value:'value'}
// + f('key>','value') => {key:'key',value:{$gte:'value'}}
// + f('key') => {key:'key',value:{$exists: true}}
// + f('!key') => {key:'key',value:{$exists: falseS}}
function comparisonToMongo(key, value) {
var join = (value == '') ? key : key.concat('=', value)
var parts = join.match(/([^><!=]+)([><]=?|!?=)(.+)/)
var parts = join.match(/^(!?[^><!=:]+)(?:([><]=?|!?=|:.+=)(.+))?$/)
var op, hash = {}
if (!parts) return null

key = parts[1]
op = parts[2]

if (op == '=' || op == '!=') {
if (!op) {
if (key[0] != '!') value = { '$exists': true }
else {
key = key.substr(1)
value = { '$exists': false }
}
} else if (op == '=' || op == '!=') {
var array = []
parts[3].split(',').forEach(function(value) {
array.push(typedValue(value))
Expand Down Expand Up @@ -115,12 +123,16 @@ function queryCriteriaToMongo(query, options) {
deep = (typeof query[key] === 'object' && !hasOrdinalKeys(query[key]))

if (deep) {
hash[key] = queryCriteriaToMongo(query[key])
p = {
key: key,
value: queryCriteriaToMongo(query[key])
}
} else {
p = comparisonToMongo(key, query[key])
if (p) {
hash[p.key] = p.value
}
}

if (p) {
hash[p.key] = p.value
}
}
}
Expand Down
12 changes: 11 additions & 1 deletion test/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ describe("query-to-mongo(query) =>", function () {
assert.deepEqual(results.criteria, {field: {"$nin": ["a","b"]}})
})
it("should ignore criteria", function () {
var results = q2m("field=value&envelope=true&&offset=0&limit=10&fields=id,name&sort=name", { ignore: ['envelope']})
var results = q2m("field=value&envelope=true&&offset=0&limit=10&fields=id&sort=name", { ignore: ['envelope']})
assert.ok(results.criteria)
assert.notOk(results.criteria.envelope, "envelope")
assert.notOk(results.criteria.skip, "offset")
Expand All @@ -137,6 +137,16 @@ describe("query-to-mongo(query) =>", function () {
assert.notOk(results.criteria.sort, "sort")
assert.deepEqual(results.criteria, {field: "value"})
})
it("should create $exists true criteria", function () {
var results = q2m("a&b=10&c", { ignore: ['c']})
assert.ok(results.criteria)
assert.deepEqual(results.criteria, {a: {"$exists": true}, b: 10})
})
it("should create $exists false criteria", function () {
var results = q2m("!a&b=10&c", { ignore: ['c']})
assert.ok(results.criteria)
assert.deepEqual(results.criteria, {a: {"$exists": false}, b: 10})
})
})

describe(".options", function () {
Expand Down

0 comments on commit c72934c

Please sign in to comment.