diff --git a/src/AbstractFirestoreRepository.ts b/src/AbstractFirestoreRepository.ts index 77d8a79e..0d6b033d 100644 --- a/src/AbstractFirestoreRepository.ts +++ b/src/AbstractFirestoreRepository.ts @@ -269,6 +269,21 @@ export abstract class AbstractFirestoreRepository extends Bas return new QueryBuilder(this).whereIn(prop, val); } + /** + * Returns a new QueryBuilder with a filter specifying that the + * field @param prop matches none of the comparison values in @param val + * + * @param {IWherePropParam} prop field to be filtered on, where + * prop could be keyof T or a lambda where T is the first parameter + * @param {IFirestoreVal[]} val[] array of values to compare in the filter (max 10 items in array) + * @returns {QueryBuilder} A new QueryBuilder with the specified + * query applied. + * @memberof AbstractFirestoreRepository + */ + whereNotIn(prop: IWherePropParam, val: IFirestoreVal[]): IQueryBuilder { + return new QueryBuilder(this).whereNotIn(prop, val); + } + /** * Returns a new QueryBuilder with a maximum number of results * to return. Can only be used once per query. diff --git a/src/BaseFirestoreRepository.spec.ts b/src/BaseFirestoreRepository.spec.ts index 12f92cf8..8886bbfe 100644 --- a/src/BaseFirestoreRepository.spec.ts +++ b/src/BaseFirestoreRepository.spec.ts @@ -443,6 +443,11 @@ describe('BaseFirestoreRepository', () => { expect(list.length).toEqual(3); }); + it('must filter with whereNotIn', async () => { + const list = await bandRepository.whereNotIn('formationYear', [1965]).find(); + expect(list.length).toEqual(2); + }); + it('should throw with whereArrayContainsAny and more than 10 items in val array', async () => { expect(async () => { await bandRepository @@ -457,6 +462,12 @@ describe('BaseFirestoreRepository', () => { }).rejects.toThrow(Error); }); + it('should throw with whereNotIn and more than 10 items in val array', async () => { + expect(async () => { + await bandRepository.whereNotIn('formationYear', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]).find(); + }).rejects.toThrow(Error); + }); + it('must filter with two or more operators', async () => { const list = await bandRepository .whereLessOrEqualThan('formationYear', 1983) diff --git a/src/QueryBuilder.ts b/src/QueryBuilder.ts index dc1dfe31..5040afe0 100644 --- a/src/QueryBuilder.ts +++ b/src/QueryBuilder.ts @@ -90,7 +90,7 @@ export default class QueryBuilder implements IQueryBuilder if (val.length > 10) { throw new Error(` This query supports up to 10 values. You provided ${val.length}. - For details please visit: https://firebase.google.com/docs/firestore/query-data/queries#in_and_array-contains-any + For details please visit: https://firebase.google.com/docs/firestore/query-data/queries#in_not-in_and_array-contains-any `); } this.queries.push({ @@ -105,7 +105,7 @@ export default class QueryBuilder implements IQueryBuilder if (val.length > 10) { throw new Error(` This query supports up to 10 values. You provided ${val.length}. - For details please visit: https://firebase.google.com/docs/firestore/query-data/queries#in_and_array-contains-any + For details please visit: https://firebase.google.com/docs/firestore/query-data/queries#in_not-in_and_array-contains-any `); } this.queries.push({ @@ -116,6 +116,21 @@ export default class QueryBuilder implements IQueryBuilder return this; } + whereNotIn(prop: IWherePropParam, val: IFirestoreVal[]) { + if (val.length > 10) { + throw new Error(` + This query supports up to 10 values. You provided ${val.length}. + For details please visit: https://firebase.google.com/docs/firestore/query-data/queries#in_not-in_and_array-contains-any + `); + } + this.queries.push({ + prop: this.extractWhereParam(prop), + val, + operator: FirestoreOperators.notIn, + }); + return this; + } + limit(limitVal: number) { if (this.limitVal) { throw new Error( diff --git a/src/types.ts b/src/types.ts index 8584c0dd..7a2ea5ff 100644 --- a/src/types.ts +++ b/src/types.ts @@ -18,6 +18,7 @@ export enum FirestoreOperators { arrayContains = 'array-contains', arrayContainsAny = 'array-contains-any', in = 'in', + notIn = 'not-in' } export interface IFireOrmQueryLine { @@ -45,6 +46,7 @@ export interface IQueryable { whereArrayContains(prop: IWherePropParam, val: IFirestoreVal): IQueryBuilder; whereArrayContainsAny(prop: IWherePropParam, val: IFirestoreVal[]): IQueryBuilder; whereIn(prop: IWherePropParam, val: IFirestoreVal[]): IQueryBuilder; + whereNotIn(prop: IWherePropParam, val: IFirestoreVal[]): IQueryBuilder; find(): Promise; findOne(): Promise; }