diff --git a/README.md b/README.md index d6bf0be..0d68a4e 100644 --- a/README.md +++ b/README.md @@ -261,6 +261,9 @@ Note that all this eager related options are optional. See [`withSchema`](https://vincit.github.io/objection.js/api/query-builder/find-methods.html#withschema) documentation. +- **`modifierFiltersResults`** - when `false` the `total` count of a `find()` query is calculated from the original result set, ignoring the `count` of any `$modify` query. + The default behaviour is to apply the count of the modifier to the result total, assuming that the modifier may influence the result total by filtering the result set. This can be used to workaround issues with `groupBy` and the result count. See [this issue](https://github.com/feathersjs-ecosystem/feathers-objection/issues/102) for a detailed explanation. + ### Composite primary keys Composite primary keys can be passed as the `id` argument using the following diff --git a/src/index.js b/src/index.js index 5673d9c..c786783 100644 --- a/src/index.js +++ b/src/index.js @@ -574,7 +574,7 @@ class Service extends AdapterService { countQuery.count({ total: countColumns }); } - if (query && query.$modify) { + if (query && query.$modify && params.modifierFiltersResults !== false) { this.modifyQuery(countQuery, query.$modify); } diff --git a/test/company.js b/test/company.js index fdb1b3e..4371ff4 100644 --- a/test/company.js +++ b/test/company.js @@ -57,6 +57,9 @@ export default class Company extends Model { }, withRelation: builder => { builder.withGraphFetched('employees'); + }, + withRelationAndGroupBy: builder => { + builder.withGraphFetched('employees').groupBy('id'); } } diff --git a/test/index.test.js b/test/index.test.js index 60b691c..6e7ff98 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -2098,6 +2098,49 @@ describe('Feathers Objection Service', () => { }); }); + it('params.modifierFiltersResults=false does not apply count from modify query', () => { + companies.options.paginate = { + default: 2, + max: 2 + }; + + return companies.find({ + query: { $modify: ['withRelationAndGroupBy'] }, modifierFiltersResults: false + }).then(data => { + expect(data.total).to.be.equal(2); + expect(data.data.length).to.be.equal(2); + expect(data.data[0].name).to.be.equal('Google'); + }); + }); + + it('params.modifierFiltersResults=true applies count from modify query', () => { + companies.options.paginate = { + default: 2, + max: 2 + }; + + return companies.find({ + query: { $modify: ['withRelationAndGroupBy'] }, modifierFiltersResults: true + }).then(data => { + expect(data.total).to.be.equal(1); // count result from GROUP BY + expect(data.data.length).to.be.equal(2); + expect(data.data[0].name).to.be.equal('Google'); + }); + }); + + it('params.modifierFiltersResults=undefined applies count from modify query', () => { + companies.options.paginate = { + default: 2, + max: 2 + }; + + return companies.find({ query: { $modify: ['withRelationAndGroupBy'] } }).then(data => { + expect(data.total).to.be.equal(1); // count result from GROUP BY + expect(data.data.length).to.be.equal(2); + expect(data.data[0].name).to.be.equal('Google'); + }); + }); + it('allow $modify query with paginate, groupBy and joinRelation', () => { companies.options.paginate = { default: 1,