diff --git a/package.json b/package.json index b9aaa8e8..d484a908 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hawk.api", - "version": "1.5.0", + "version": "1.5.1", "main": "index.ts", "license": "BUSL-1.1", "scripts": { diff --git a/src/dataLoaders.ts b/src/dataLoaders.ts index 377bd702..cb5c0a2e 100644 --- a/src/dataLoaders.ts +++ b/src/dataLoaders.ts @@ -68,12 +68,19 @@ export default class DataLoaders { * Batching function for resolving entities from their ids * @param collectionName - collection name to get entities * @param ids - ids for resolving + * @param projection - optional mongo projection to limit returned fields */ private async batchByIds( collectionName: string, - ids: ReadonlyArray + ids: ReadonlyArray, + projection?: Record ): Promise<(WithId | null)[]> { - return this.batchByField(collectionName, '_id', ids.map(id => new ObjectId(id))); + return this.batchByField( + collectionName, + '_id', + ids.map(id => new ObjectId(id)), + projection + ); } /** @@ -81,6 +88,7 @@ export default class DataLoaders { * @param collectionName - collection name to get entities * @param fieldName - field name to resolve * @param values - values for resolving + * @param projection - optional mongo projection to limit returned fields */ private async batchByField< T extends Record, @@ -88,7 +96,8 @@ export default class DataLoaders { >( collectionName: string, fieldName: FieldType, - values: ReadonlyArray + values: ReadonlyArray, + projection?: Record ): Promise<(WithId | null)[]> { type Doc = WithId; const valuesMap = new Map(); @@ -99,9 +108,10 @@ export default class DataLoaders { const queryResult = await this.dbConnection .collection(collectionName) - .find({ - [fieldName]: { $in: Array.from(valuesMap.values()) }, - } as any) + .find( + { [fieldName]: { $in: Array.from(valuesMap.values()) } } as any, + projection ? { projection } : {} + ) .toArray(); /** diff --git a/src/models/eventsFactory.js b/src/models/eventsFactory.js index c552bc41..9424440d 100644 --- a/src/models/eventsFactory.js +++ b/src/models/eventsFactory.js @@ -403,6 +403,17 @@ class EventsFactory extends Factory { return { 'event.assignee': String(assignee) }; })(); + /** When false, $limit can move before the $lookups. */ + const hasContentFilters = + escapedSearch.length > 0 || + Boolean(release) || + Boolean(assignee) || + Object.keys(matchFilter).length > 0; + + if (!hasContentFilters) { + pipeline.push({ $limit: limit + 1 }); + } + pipeline.push( /** * Left outer join original event on groupHash field @@ -434,21 +445,25 @@ class EventsFactory extends Factory { path: '$repetition', preserveNullAndEmptyArrays: true, }, - }, - { - $match: { - ...matchFilter, - ...searchFilter, - ...releaseFilter, - ...assigneeFilter, - }, - }, - { $limit: limit + 1 }, - { - $unset: 'groupHash', } ); + if (hasContentFilters) { + pipeline.push( + { + $match: { + ...matchFilter, + ...searchFilter, + ...releaseFilter, + ...assigneeFilter, + }, + }, + { $limit: limit + 1 } + ); + } + + pipeline.push({ $unset: 'groupHash' }); + const cursor = this.getCollection(this.TYPES.DAILY_EVENTS).aggregate(pipeline); const result = await cursor.toArray();