Skip to content

Commit d27f79a

Browse files
committed
feat: nested aliases are now supported for filter, projection & lean
1 parent deb5de8 commit d27f79a

File tree

18 files changed

+393
-137
lines changed

18 files changed

+393
-137
lines changed

src/__tests__/github_issues/271-test.ts

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,57 @@ describe('nested projections with aliases - issue #271', () => {
175175
data: { booksMany: [{ author: { isAbove100: 'yes' }, bookSize: 'big' }] },
176176
});
177177
});
178+
179+
it('check filter with alias', async () => {
180+
// firstly check mongoose query
181+
expect(await BookModel.find({ pc: 1168 }).lean()).toEqual([
182+
{
183+
__v: 0,
184+
_id: 1,
185+
a: { ag: 115, isAlive: false, name: 'Ayn Rand' },
186+
pc: 1168,
187+
title: 'Atlas Shrugged',
188+
},
189+
]);
190+
191+
// check that aliases correctly applied to filter
192+
const result = await graphql.graphql({
193+
schema,
194+
source: `
195+
query {
196+
booksMany(filter: { pageCount: 1168 }) {
197+
title
198+
pageCount
199+
}
200+
}`,
201+
contextValue: {},
202+
});
203+
expect(result).toEqual({ data: { booksMany: [{ pageCount: 1168, title: 'Atlas Shrugged' }] } });
204+
});
205+
206+
it('check nested filter with alias', async () => {
207+
// firstly check mongoose query
208+
expect(await BookModel.find({ 'a.ag': 115 }).lean()).toEqual([
209+
{
210+
__v: 0,
211+
_id: 1,
212+
a: { ag: 115, isAlive: false, name: 'Ayn Rand' },
213+
pc: 1168,
214+
title: 'Atlas Shrugged',
215+
},
216+
]);
217+
218+
const result = await graphql.graphql({
219+
schema,
220+
source: `
221+
query {
222+
booksMany(filter: { author: { age: 115 } }) {
223+
title
224+
pageCount
225+
}
226+
}`,
227+
contextValue: {},
228+
});
229+
expect(result).toEqual({ data: { booksMany: [{ pageCount: 1168, title: 'Atlas Shrugged' }] } });
230+
});
178231
});

src/resolvers/count.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import type { Resolver, ObjectTypeComposer } from 'graphql-compose';
22
import type { Model, Document } from 'mongoose';
3-
import { filterHelper, filterHelperArgs, prepareAliases, FilterHelperArgsOpts } from './helpers';
3+
import {
4+
filterHelper,
5+
filterHelperArgs,
6+
FilterHelperArgsOpts,
7+
prepareNestedAliases,
8+
} from './helpers';
49
import type { ExtendedResolveParams } from './index';
510
import { beforeQueryHelper } from './helpers/beforeQueryHelper';
611

@@ -28,7 +33,7 @@ export function count<TSource = any, TContext = any, TDoc extends Document = any
2833
throw new Error('Second arg for Resolver count() should be instance of ObjectTypeComposer.');
2934
}
3035

31-
const aliases = prepareAliases(model);
36+
const aliases = prepareNestedAliases(model.schema);
3237

3338
return tc.schemaComposer.createResolver<TSource, TArgs>({
3439
type: 'Int',

src/resolvers/dataLoader.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { toInputType } from 'graphql-compose';
22
import type { Resolver, ObjectTypeComposer } from 'graphql-compose';
33
import type { Model, Document } from 'mongoose';
4-
import { projectionHelper, prepareAliases, prepareAliasesReverse, replaceAliases } from './helpers';
4+
import {
5+
projectionHelper,
6+
prepareNestedAliases,
7+
prepareAliasesReverse,
8+
replaceAliases,
9+
} from './helpers';
510
import type { ExtendedResolveParams } from './index';
611
import { beforeQueryHelper, beforeQueryHelperLean } from './helpers/beforeQueryHelper';
712
import { getDataLoader } from './helpers/dataLoaderHelper';
@@ -41,8 +46,8 @@ export function dataLoader<TSource = any, TContext = any, TDoc extends Document
4146
);
4247
}
4348

44-
const aliases = prepareAliases(model);
45-
const aliasesReverse = prepareAliasesReverse(model);
49+
const aliases = prepareNestedAliases(model.schema);
50+
const aliasesReverse = prepareAliasesReverse(model.schema);
4651

4752
return tc.schemaComposer.createResolver<TSource, TArgs>({
4853
type: tc,

src/resolvers/dataLoaderMany.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { toInputType } from 'graphql-compose';
22
import type { Resolver, ObjectTypeComposer } from 'graphql-compose';
33
import type { Model, Document } from 'mongoose';
4-
import { projectionHelper, prepareAliases, prepareAliasesReverse, replaceAliases } from './helpers';
4+
import {
5+
projectionHelper,
6+
prepareNestedAliases,
7+
prepareAliasesReverse,
8+
replaceAliases,
9+
} from './helpers';
510
import type { ExtendedResolveParams } from './index';
611
import { beforeQueryHelper, beforeQueryHelperLean } from './helpers/beforeQueryHelper';
712
import { getDataLoader } from './helpers/dataLoaderHelper';
@@ -43,8 +48,8 @@ export function dataLoaderMany<TSource = any, TContext = any, TDoc extends Docum
4348
);
4449
}
4550

46-
const aliases = prepareAliases(model);
47-
const aliasesReverse = prepareAliasesReverse(model);
51+
const aliases = prepareNestedAliases(model.schema);
52+
const aliasesReverse = prepareAliasesReverse(model.schema);
4853

4954
return tc.schemaComposer.createResolver<TSource, TArgs>({
5055
type: tc.List.NonNull,

src/resolvers/findById.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { toInputType } from 'graphql-compose';
22
import type { Resolver, ObjectTypeComposer } from 'graphql-compose';
33
import type { Model, Document } from 'mongoose';
4-
import { projectionHelper, prepareAliases, prepareAliasesReverse, replaceAliases } from './helpers';
4+
import {
5+
projectionHelper,
6+
prepareNestedAliases,
7+
prepareAliasesReverse,
8+
replaceAliases,
9+
} from './helpers';
510
import type { ExtendedResolveParams } from './index';
611
import { beforeQueryHelper, beforeQueryHelperLean } from './helpers/beforeQueryHelper';
712

@@ -38,8 +43,8 @@ export function findById<TSource = any, TContext = any, TDoc extends Document =
3843
throw new Error('Second arg for Resolver findById() should be instance of ObjectTypeComposer.');
3944
}
4045

41-
const aliases = prepareAliases(model);
42-
const aliasesReverse = prepareAliasesReverse(model);
46+
const aliases = prepareNestedAliases(model.schema);
47+
const aliasesReverse = prepareAliasesReverse(model.schema);
4348

4449
return tc.schemaComposer.createResolver<TSource, TArgs>({
4550
type: tc,

src/resolvers/findByIds.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
sortHelper,
88
sortHelperArgs,
99
projectionHelper,
10-
prepareAliases,
10+
prepareNestedAliases,
1111
prepareAliasesReverse,
1212
replaceAliases,
1313
LimitHelperArgsOpts,
@@ -54,8 +54,8 @@ export function findByIds<TSource = any, TContext = any, TDoc extends Document =
5454
);
5555
}
5656

57-
const aliases = prepareAliases(model);
58-
const aliasesReverse = prepareAliasesReverse(model);
57+
const aliases = prepareNestedAliases(model.schema);
58+
const aliasesReverse = prepareAliasesReverse(model.schema);
5959

6060
return tc.schemaComposer.createResolver<TSource, TArgs>({
6161
type: tc.NonNull.List.NonNull,

src/resolvers/findMany.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
sortHelper,
1111
sortHelperArgs,
1212
projectionHelper,
13-
prepareAliases,
13+
prepareNestedAliases,
1414
prepareAliasesReverse,
1515
replaceAliases,
1616
FilterHelperArgsOpts,
@@ -62,8 +62,8 @@ export function findMany<TSource = any, TContext = any, TDoc extends Document =
6262
throw new Error('Second arg for Resolver findMany() should be instance of ObjectTypeComposer.');
6363
}
6464

65-
const aliases = prepareAliases(model);
66-
const aliasesReverse = prepareAliasesReverse(model);
65+
const aliases = prepareNestedAliases(model.schema);
66+
const aliasesReverse = prepareAliasesReverse(model.schema);
6767

6868
return tc.schemaComposer.createResolver<TSource, TArgs>({
6969
type: tc.NonNull.List.NonNull,

src/resolvers/findOne.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
sortHelper,
99
sortHelperArgs,
1010
projectionHelper,
11-
prepareAliases,
11+
prepareNestedAliases,
1212
prepareAliasesReverse,
1313
replaceAliases,
1414
FilterHelperArgsOpts,
@@ -57,8 +57,8 @@ export function findOne<TSource = any, TContext = any, TDoc extends Document = a
5757
throw new Error('Second arg for Resolver findOne() should be instance of ObjectTypeComposer.');
5858
}
5959

60-
const aliases = prepareAliases(model);
61-
const aliasesReverse = prepareAliasesReverse(model);
60+
const aliases = prepareNestedAliases(model.schema);
61+
const aliasesReverse = prepareAliasesReverse(model.schema);
6262

6363
return tc.schemaComposer.createResolver<TSource, TArgs>({
6464
type: tc,

src/resolvers/helpers/__tests__/filter-test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ import { filterHelperArgs, filterHelper } from '../filter';
88
import { OPERATORS_FIELDNAME } from '../filterOperators';
99
import { UserModel } from '../../../__mocks__/userModel';
1010
import { convertModelToGraphQL } from '../../../fieldsConverter';
11-
import { prepareAliases } from '../aliases';
11+
import { prepareNestedAliases } from '../aliases';
1212

1313
describe('Resolver helper `filter` ->', () => {
1414
let UserTC: ObjectTypeComposer<any, any>;
15-
const aliases = prepareAliases(UserModel);
15+
const aliases = prepareNestedAliases(UserModel.schema);
1616

1717
beforeEach(() => {
1818
schemaComposer.clear();

src/resolvers/helpers/__tests__/projection-test.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('Resolver helper `projection` ->', () => {
1515
});
1616

1717
it('should not call query.select if projection is empty', () => {
18-
projectionHelper(resolveParams, false);
18+
projectionHelper(resolveParams);
1919
expect(spyFn).not.toBeCalled();
2020
});
2121

@@ -31,29 +31,35 @@ describe('Resolver helper `projection` ->', () => {
3131
expect(spyFn).toBeCalledWith({ 'n.first': true, 'n.last': true });
3232
});
3333

34+
it('should make projection fields flat with nested aliases', () => {
35+
resolveParams.projection = { name: { first: 1, last: 1 } };
36+
projectionHelper(resolveParams, { name: { __selfAlias: 'n', first: 'f', last: 'l' } });
37+
expect(spyFn).toBeCalledWith({ 'n.f': true, 'n.l': true });
38+
});
39+
3440
it('should not call query.select if projection has * key', () => {
3541
resolveParams.projection = { '*': true };
36-
projectionHelper(resolveParams, false);
42+
projectionHelper(resolveParams);
3743
expect(spyFn).not.toBeCalled();
3844
});
3945

4046
describe('projection operators', () => {
4147
// see more details here https://docs.mongodb.com/v3.2/reference/operator/projection/meta/
42-
it('should pass $meta unflatted', () => {
48+
it('should pass $meta non-flatten', () => {
4349
resolveParams.projection = { score: { $meta: 'textScore' } };
44-
projectionHelper(resolveParams, false);
50+
projectionHelper(resolveParams);
4551
expect(spyFn).toBeCalledWith({ score: { $meta: 'textScore' } });
4652
});
4753

48-
it('should pass $slice unflatted', () => {
54+
it('should pass $slice non-flatten', () => {
4955
resolveParams.projection = { comments: { $slice: 5 } };
50-
projectionHelper(resolveParams, false);
56+
projectionHelper(resolveParams);
5157
expect(spyFn).toBeCalledWith({ comments: { $slice: 5 } });
5258
});
5359

54-
it('should pass $elemMatch unflatted', () => {
60+
it('should pass $elemMatch non-flatten', () => {
5561
resolveParams.projection = { students: { $elemMatch: { school: 102 } } };
56-
projectionHelper(resolveParams, false);
62+
projectionHelper(resolveParams);
5763
expect(spyFn).toBeCalledWith({ students: { $elemMatch: { school: 102 } } });
5864
});
5965
});

0 commit comments

Comments
 (0)