Skip to content

Commit

Permalink
feat(mongodb): Add support for all filter operators
Browse files Browse the repository at this point in the history
  • Loading branch information
marian2js authored and doug-martin committed Oct 16, 2020
1 parent 702dc83 commit 9420036
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,94 @@ describe('TypegooseQueryService', () => {

describe('#query', () => {
it('call find and return the result', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({});
return expect(queryResult).toHaveLength(TEST_ENTITIES.length);
});

it('should support eq operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { stringType: { eq: 'foo1' } } });
return expect(queryResult).toEqual([TEST_ENTITIES[0]]);
});

it('should support neq operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { stringType: { neq: 'foo1' } } });
return expect(queryResult).toHaveLength(TEST_ENTITIES.length - 1);
});

it('should support gt operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { numberType: { gt: 5 } } });
return expect(queryResult).toHaveLength(TEST_ENTITIES.length - 5);
});

it('should support gte operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { numberType: { gte: 5 } } });
return expect(queryResult).toHaveLength(TEST_ENTITIES.length - 4);
});

it('should support lt operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { numberType: { lt: 10 } } });
return expect(queryResult).toHaveLength(9);
});

it('should support lte operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { numberType: { lte: 10 } } });
return expect(queryResult).toHaveLength(10);
});

it('should support in operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { numberType: { in: [1, 2, 3] } } });
return expect(queryResult).toEqual([TEST_ENTITIES[0], TEST_ENTITIES[1], TEST_ENTITIES[2]]);
});

it('should support notIn operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { numberType: { notIn: [1, 2, 3] } } });
return expect(queryResult).toHaveLength(12);
});

it('should support is operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { boolType: { is: true } } });
return expect(queryResult).toHaveLength(7);
});

it('should support isNot operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { boolType: { isNot: true } } });
return expect(queryResult).toHaveLength(8);
});

it('should support like operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { stringType: { like: 'foo%' } } });
return expect(queryResult).toHaveLength(15);
});

it('should support notLike operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { stringType: { notLike: 'foo%' } } });
return expect(queryResult).toHaveLength(0);
});

it('should support iLike operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { stringType: { iLike: 'FOO%' } } });
return expect(queryResult).toHaveLength(15);
});

it('should support notILike operator', async () => {
const queryService = moduleRef.get(TestEntityService);
const queryResult = await queryService.query({ filter: { stringType: { notILike: 'FOO%' } } });
return expect(queryResult).toHaveLength(0);
});
});

describe('#count', () => {
Expand Down
6 changes: 2 additions & 4 deletions packages/query-typegoose/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
},
"dependencies": {
"@nestjs-query/core": "0.18.1",
"lodash.filter": "^4.6.0",
"lodash.omit": "^4.5.0"
"lodash.escaperegexp": "^4.1.2"
},
"peerDependencies": {
"@nestjs/common": "^7.0.0",
Expand All @@ -33,8 +32,7 @@
"@nestjs/common": "7.4.2",
"@nestjs/testing": "7.4.2",
"@typegoose/typegoose": "^7.3.3",
"@types/lodash.filter": "4.6.6",
"@types/lodash.omit": "4.5.6",
"@types/lodash.escaperegexp": "^4.1.6",
"@types/mongodb": "^3.5.26",
"@types/mongoose": "^5.7.36",
"class-transformer": "0.3.1",
Expand Down
17 changes: 17 additions & 0 deletions packages/query-typegoose/src/services/typegoose-query.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import { Logger, NotFoundException } from '@nestjs/common';
import { FilterQuery, UpdateQuery } from 'mongoose';
import { ReturnModelType } from '@typegoose/typegoose';
import escapeRegExp from 'lodash.escaperegexp';

const mongoOperatorMapper: { [k: string]: string } = {
eq: '$eq',
Expand All @@ -22,6 +23,8 @@ const mongoOperatorMapper: { [k: string]: string } = {
lte: '$lte',
in: '$in',
notIn: '$nin',
is: '$eq',
isNot: '$ne',
};

/**
Expand Down Expand Up @@ -64,6 +67,20 @@ export class TypegooseQueryService<Entity> implements QueryService<Entity> {
[mongoOperatorMapper[fieldKey]]: fieldValue,
};
}
if (['like', 'notLike', 'iLike', 'notILike'].includes(fieldKey)) {
const regExpStr = (escapeRegExp as (str: string) => string)(fieldValue as string).replace('%', '.*');
const regExp = new RegExp(regExpStr, fieldKey.toLowerCase().includes('ilike') ? 'i' : undefined);
if (fieldKey.startsWith('not')) {
return {
...prevCondition,
$not: { $regex: regExp },
};
}
return {
...prevCondition,
$regex: regExp,
};
}
this.logger.error(`Operator ${fieldKey} not supported yet`);
return prevCondition;
},
Expand Down

0 comments on commit 9420036

Please sign in to comment.