Skip to content

Commit

Permalink
distinctAndCount on some kind of object fields
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielelana committed Dec 5, 2014
1 parent cfeeb17 commit fd270c3
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 14 deletions.
56 changes: 46 additions & 10 deletions spec/distinct_and_count.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
assert.that('distinctAndCount on one field', function(c) {
/* global NumberLong:false */

assert.that('distinctAndCount works on one field', function(c) {
c.save({field: 'value_1'})
c.save({field: 'value_2'})
c.save({field: 'value_1'})
Expand All @@ -9,7 +11,7 @@ assert.that('distinctAndCount on one field', function(c) {
assert.eq(1, result['value_2'])
})

assert.that('distinctAndCount on one nested field', function(c) {
assert.that('distinctAndCount works on one nested field', function(c) {
c.save({field: {nested: 'value_1'}})
c.save({field: {nested: 'value_2'}})
c.save({field: {nested: 'value_1'}})
Expand All @@ -20,7 +22,7 @@ assert.that('distinctAndCount on one nested field', function(c) {
assert.eq(1, result['value_2'])
})

assert.that('distinctAndCount on deeply nested fields', function(c) {
assert.that('distinctAndCount works on deeply nested fields', function(c) {
c.save({field: {nested: {nested: {nested: 'value_1'}}}})
c.save({field: {nested: {nested: {nested: 'value_2'}}}})
c.save({field: {nested: {nested: {nested: 'value_1'}}}})
Expand All @@ -31,7 +33,7 @@ assert.that('distinctAndCount on deeply nested fields', function(c) {
assert.eq(1, result['value_2'])
})

assert.that('distinctAndCount on multiple fields', function(c) {
assert.that('distinctAndCount works on multiple fields', function(c) {
c.save({'field_1': 'value_1', 'field_2': 'value_1'})
c.save({'field_1': 'value_2', 'field_2': 'value_2'})
c.save({'field_1': 'value_1', 'field_2': 'value_3'})
Expand All @@ -44,22 +46,56 @@ assert.that('distinctAndCount on multiple fields', function(c) {
assert.eq(1, result['value_1,value_1'])
})

assert.that('distinctAndCount throws an exception with array fields', function(c) {
assert.that('distinctAndCount works on array fields', function(c) {
c.save({field: 'value_1'})
c.save({field: ['value_2', 'value_3']})
c.save({field: ['value_3', 'value_2']})
c.save({field: ['value_1', 'value_2']})

var result = c.distinctAndCount('field')

assert.eq(1, result['value_1'])
assert.eq(2, result['value_2,value_3'])
assert.eq(1, result['value_1,value_2'])
})

assert.that('distinctAndCount works on multiple array fields', function(c) {
c.save({'field_1': ['value_1','value_2'], 'field_2': 'value_1'})
c.save({'field_1': ['value_1','value_2'], 'field_2': 'value_2'})
c.save({'field_1': ['value_2','value_1'], 'field_2': 'value_2'})

var result = c.distinctAndCount(['field_1', 'field_2'])

assert.eq(1, result['value_1,value_2,value_1'])
assert.eq(2, result['value_1,value_2,value_2'])
})

assert.that('distinctAndCount throws an exception on object fields', function(c) {
c.save({field: 'value_1'})
c.save({field: ['value_2']})
c.save({field: {key: 'value_2'}})

assert.throws(function() {
c.distinctAndCount('field')
}, [])
})
})

assert.that('distinctAndCount throws an exception with object fields', function(c) {
assert.that('distinctAndCount throws an exception on array fields that contains objects', function(c) {
c.save({field: 'value_1'})
c.save({field: {key: 'value_2'}})
c.save({field: [{key: 'value_2'}]})

assert.throws(function() {
c.distinctAndCount('field')
}, [])
})
})

assert.that('distinctAndCount works with Number fields', function(c) {
c.save({field: 'value_1'})
c.save({field: NumberLong(200)})

var result = c.distinctAndCount('field')

assert.eq(1, result['value_1'])
assert.eq(1, result[200])
})

assert.that('distinctAndCount takes a query as second parameter', function(c) {
Expand Down
42 changes: 38 additions & 4 deletions src/distinct_and_count.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,44 @@ DBCollection.prototype.distinctAndCount = function(field, query) {

var result = it.result || it.toArray()
return _.reduce(result, function(all, r) {
if (!_.any(r.values, isObject)) {
all[_.values(r.values).join(',')] = r.count
return all

var isValidValue =
_(r.values)
.chain()
.values()
.any(function(value) {
if (_(value).isArray()) {
return _(value).all(function(value) {
return !_(value).isObject()
})
}
// we support values like Number or Date but not {}
return value.constructor.name !== ''
})
.valueOf()

if (!isValidValue) {
throw 'distinctAndCount could not work when one or more fields are objects: ' + tojson(r.values)
}
throw 'distinctAndCount fields could not be objects: ' + tojson(r.values)

var key =
_(r.values)
.chain()
.values()
.map(function(value) {
if (_(value.valueOf).isFunction()) {
value = value.valueOf()
}
if (_(value).isArray()) {
value = _(value).sort().valueOf()
}
return value
})
.valueOf()
.join(',')

all[key] = (all[key] || 0) + r.count

return all
}, {})
}

0 comments on commit fd270c3

Please sign in to comment.