Skip to content

Commit

Permalink
Add HAS operator
Browse files Browse the repository at this point in the history
  • Loading branch information
DropsOfSerenity committed May 4, 2022
1 parent 11dd7c2 commit d5f07a4
Show file tree
Hide file tree
Showing 7 changed files with 3,657 additions and 23 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,5 @@ A list of all operators are as follows:
| `lte` | less than or equal to |
| `startswith` | starts with |
| `endswith` | ends with |
| `has` | array has any element |

14 changes: 10 additions & 4 deletions lib/sort-and-filter.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {
createParamDecorator, ExecutionContext
} from '@nestjs/common';
import { Equal, FindManyOptions, FindOperator, ILike, LessThan, LessThanOrEqual, Like, MoreThan, MoreThanOrEqual, Not, ObjectLiteral, SelectQueryBuilder } from 'typeorm';
import { Equal, FindManyOptions, FindOperator, ILike, In, LessThan, LessThanOrEqual, Like, MoreThan, MoreThanOrEqual, Not, ObjectLiteral, SelectQueryBuilder } from 'typeorm';

export enum SearchOps {
EQUALS = 'eq',
Expand All @@ -13,7 +13,8 @@ export enum SearchOps {
GTE = 'gte',
LTE = 'lte',
STARTSWITH = 'startswith',
ENDSWITH = 'endswith'
ENDSWITH = 'endswith',
HAS = 'has',
}

export interface SortAndFilterParams {
Expand Down Expand Up @@ -107,6 +108,7 @@ const searchOpToOperator = {
[SearchOps.LT]: '<',
[SearchOps.GTE]: '>=',
[SearchOps.LTE]: '<=',
[SearchOps.HAS]: '@>',
};

function NotEqual<T>(value: T | FindOperator<T>): FindOperator<T> {
Expand All @@ -125,6 +127,7 @@ const searchOpToTypeormOperator = {
[SearchOps.LT]: LessThan,
[SearchOps.GTE]: MoreThanOrEqual,
[SearchOps.LTE]: LessThanOrEqual,
[SearchOps.HAS]: In,
};

function paramTransform(param: string, op: SearchOps) {
Expand All @@ -135,7 +138,9 @@ function paramTransform(param: string, op: SearchOps) {
case SearchOps.STARTSWITH:
return `${param}%`
case SearchOps.ENDSWITH:
return `%${param}`
return `%${param}`;
case SearchOps.HAS:
return [param.split(',')];
}

return param;
Expand Down Expand Up @@ -177,6 +182,7 @@ SelectQueryBuilder.prototype.sortAndFilter = function<Entity>(this: SelectQueryB
}
}


return this;
};

Expand All @@ -202,4 +208,4 @@ export const sortAndFilter = <T extends ObjectLiteral>(params: SortAndFilterPara
}

return options;
}
}
52 changes: 51 additions & 1 deletion lib/spec/all.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { expect } from "chai";
import supertest = require("supertest");
import {In} from "typeorm";
import { TestFactory } from "./factories";
import { app } from "./helper";
import { app, connection } from "./helper";
import {SomeEnum, Test} from "./test-app/test.entity";

let testFactory = new TestFactory();

Expand Down Expand Up @@ -82,6 +84,54 @@ let testFactory = new TestFactory();
expect(body.results[0].id).to.eq(record.id);
});

it('can filter arrays', async () => {
const record = await testFactory.create({
name: 'name',
email: '[email protected]',
});
record.someArray = [SomeEnum.Choice1, SomeEnum.Choice3];
await record.save();


const url = `/tests?filter=someArray__has:2`;
const res = await supertest(app.getHttpServer()).get(url);
const { body } = res;

expect(body.results.length).to.eq(0);
});

it('can filter arrays by multiple values', async () => {
const record = await testFactory.create({
name: 'name',
email: '[email protected]',
});
record.someArray = [SomeEnum.Choice1, SomeEnum.Choice3];
await record.save();


const url = `/tests?filter=someArray__has:1,2`;
const res = await supertest(app.getHttpServer()).get(url);
const { body } = res;

expect(body.results.length).to.eq(1);
});

it('can filter arrays by multiple invalid values', async () => {
const record = await testFactory.create({
name: 'name',
email: '[email protected]',
});
record.someArray = [SomeEnum.Choice1, SomeEnum.Choice3];
await record.save();


const url = `/tests?filter=someArray__has:2,4`;
const res = await supertest(app.getHttpServer()).get(url);
const { body } = res;

expect(body.results.length).to.eq(0);
});

it('can "not equals" filter', async () => {
await testFactory.create({ name: 'thing' });

Expand Down
2 changes: 1 addition & 1 deletion lib/spec/test-app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ import { TestModule } from "./test.module";
TestModule
],
})
export class AppModule {};
export class AppModule {};
6 changes: 3 additions & 3 deletions lib/spec/test-app/test.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export class TestController {
}) paginateParams: PaginateParams,
@SortAndFilter({
sortable: ['name', 'email'],
filterable: ['name', 'email', 'createdAt'],
filterable: ['name', 'email', 'someArray', 'createdAt'],
}) sortAndFilterParams: SortAndFilterParams,
): Promise<Paginated<Test>> {
return this.testRepository
Expand All @@ -32,9 +32,9 @@ export class TestController {
}) paginateParams: PaginateParams,
@SortAndFilter({
sortable: ['name', 'email'],
filterable: ['name', 'email', 'createdAt'],
filterable: ['name', 'email', 'someArray', 'createdAt'],
}) sortAndFilterParams: SortAndFilterParams,
): Promise<Paginated<Test>> {
return paginate(this.testRepository, paginateParams, sortAndFilter(sortAndFilterParams));
}
}
}
16 changes: 15 additions & 1 deletion lib/spec/test-app/test.entity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";

export enum SomeEnum {
Choice1 = '1',
Choice2 = '2',
Choice3 = '3',
};

@Entity()
export class Test extends BaseEntity {
@PrimaryGeneratedColumn()
Expand All @@ -11,9 +17,17 @@ export class Test extends BaseEntity {
@Column()
email: string;

@Column({
type: 'enum',
enum: SomeEnum,
array: true,
default: '{}'
})
someArray: SomeEnum[];

@UpdateDateColumn()
updatedAt: Date;

@CreateDateColumn()
createdAt: Date;
}
}
Loading

0 comments on commit d5f07a4

Please sign in to comment.