Skip to content

Commit

Permalink
Added $modifyEager query param to filter relation based on relation's…
Browse files Browse the repository at this point in the history
… field
  • Loading branch information
Dekel Barzilay committed Dec 6, 2019
1 parent 26e3331 commit 9557659
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 47 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ Note that all this eager related options are optional.
object or array of objects with the following properties:
- `expression` - the relation expression that the filter will be applied.
- `filter` - the filter function. It uses
[`filterEager`](https://vincit.github.io/objection.js/api/query-builder/eager-methods.html#filtereager)
[`modifyEager`](https://vincit.github.io/objection.js/api/query-builder/eager-methods.html#modifyeager)
internally.
- **`namedEagerFilters`** - object containing named eager filter functions.
Filter is opt-in via `$eager` parameter.
Expand All @@ -164,6 +164,8 @@ Note that all this eager related options are optional.
`JoinEagerAlgorithm`. See
[`$joinEager`](https://vincit.github.io/objection.js/api/query-builder/eager-methods.html#joineager)
documentation.
- **`$modifyEager`** - filter relation based on a relation's field.
e.g. `companies.find({ query: { $eager: 'employees', $modifyEager: { employees: { name: 'John' } } } })`
- **`$pick`** - pick properties from result models. See
[`pick`](https://vincit.github.io/objection.js/api/query-builder/other-methods.html#pick) documentation.

Expand Down
43 changes: 12 additions & 31 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "feathers-objection",
"description": "A service plugin for ObjectionJS an ORM based on KnexJS",
"version": "4.5.2",
"version": "4.6.0",
"homepage": "https://github.com/feathersjs-ecosystem/feathers-objection",
"keywords": [
"feathers",
Expand Down
25 changes: 17 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ class Service extends AdapterService {
if (params.$eager) { delete params.$eager; }
if (params.$joinEager) { delete params.$joinEager; }
if (params.$joinRelation) { delete params.$joinRelation; }
if (params.$modifyEager) { delete params.$modifyEager; }
if (params.$pick) { delete params.$pick; }
if (params.$noSelect) { delete params.$noSelect; }

Expand Down Expand Up @@ -267,7 +268,6 @@ class Service extends AdapterService {
}

// $eager for Objection eager queries

if (query && query.$eager) {
q.eager(query.$eager, this.namedEagerFilters);
delete query.$eager;
Expand All @@ -290,14 +290,23 @@ class Service extends AdapterService {

// apply eager filters if specified
if (this.eagerFilters) {
const eagerFilters = this.eagerFilters;
if (Array.isArray(eagerFilters)) {
for (const eagerFilter of eagerFilters) {
q.filterEager(eagerFilter.expression, eagerFilter.filter);
}
} else {
q.filterEager(eagerFilters.expression, eagerFilters.filter);
const eagerFilters = Array.isArray(this.eagerFilters) ? this.eagerFilters : [this.eagerFilters];

for (const eagerFilter of eagerFilters) {
q.modifyEager(eagerFilter.expression, eagerFilter.filter);
}
}

if (query && query.$modifyEager) {
for (const eagerFilterExpression of Object.keys(query.$modifyEager)) {
const eagerFilterQuery = query.$modifyEager[eagerFilterExpression];

q.modifyEager(eagerFilterExpression, builder => {
this.objectify(builder, eagerFilterQuery);
});
}

delete query.$modifyEager;
}

if (query && query.$pick) {
Expand Down
45 changes: 39 additions & 6 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ const app = feathers()
model: Company,
id: 'id',
multi: ['create', 'remove', 'patch'],
whitelist: ['$eager', '$pick', '$between', '$notBetween', '$containsKey', '$contains', '$contained', '$any', '$all', '$noSelect', '$like'],
whitelist: ['$eager', '$modifyEager', '$pick', '$between', '$notBetween', '$containsKey', '$contains', '$contained', '$any', '$all', '$noSelect', '$like'],
allowedEager: '[ceos, clients]',
namedEagerFilters: {
notSnoop (builder) {
Expand Down Expand Up @@ -721,26 +721,52 @@ describe('Feathers Objection Service', () => {
});

describe('Eager queries', () => {
beforeEach(async () => {
const data = await people
const ids = {};

before(async () => {
ids.ceo = await people
.create({
name: 'Snoop',
age: 20
});

await companies
ids.companies = await companies
.create([
{
name: 'Google',
ceo: data.id
ceo: ids.ceo.id
},
{
name: 'Apple',
ceo: data.id
ceo: ids.ceo.id
}
]);

ids.employees = await employees
.create([
{
name: 'John',
companyId: 1
},
{
name: 'John',
companyId: 1
},
{
name: 'Dan',
companyId: 1
}
]);
});

after(async () => {
await people.remove(ids.ceo.id);

for (const company of ids.companies) { await companies.remove(company.id); }

for (const employee of ids.employees) { await employees.remove(employee.id); }
});

it('allows eager queries', () => {
return companies.find({ query: { $eager: 'ceos' } }).then(data => {
expect(data[0].ceos).to.be.ok;
Expand All @@ -753,6 +779,13 @@ describe('Feathers Objection Service', () => {
});
});

it('allows modifyEager queries', () => {
return companies.find({ query: { $eager: 'employees', $modifyEager: { employees: { name: 'John' } } }, mergeAllowEager: 'employees' }).then(data => {
expect(data[0].employees.length).to.equal(2);
expect(data[1].employees.length).to.equal(0);
});
});

it('allows eager queries with pick', () => {
return companies.find({ query: { $eager: 'ceos', $pick: ['ceos'] } }).then(data => {
expect(data[0].ceos).to.be.ok;
Expand Down

0 comments on commit 9557659

Please sign in to comment.