diff --git a/api/src/nlp/repositories/nlp-value.repository.ts b/api/src/nlp/repositories/nlp-value.repository.ts index a476c79e..99cfdd11 100644 --- a/api/src/nlp/repositories/nlp-value.repository.ts +++ b/api/src/nlp/repositories/nlp-value.repository.ts @@ -8,9 +8,10 @@ import { Injectable } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; -import { Document, Model, Query } from 'mongoose'; +import { Document, Model, Query, Types } from 'mongoose'; import { BaseRepository, DeleteResult } from '@/utils/generics/base-repository'; +import { PageQueryDto } from '@/utils/pagination/pagination-query.dto'; import { TFilterQuery } from '@/utils/types/filter.types'; import { NlpValueDto } from '../dto/nlp-value.dto'; @@ -106,4 +107,118 @@ export class NlpValueRepository extends BaseRepository< throw new Error('Attempted to delete a NLP value using unknown criteria'); } } + + async findAndPopulateNlpValuesWithCount( + populate: string[], + filters?: TFilterQuery, + pageQuery?: PageQueryDto, + ) { + const { $and = [], ...rest } = filters || ({} as TFilterQuery); + + return this.model + .aggregate([ + { + // support filters + $match: { + ...rest, + ...($and?.length && { + $and: + $and?.map((v) => { + if (v.entity) { + return { + ...v, + entity: new Types.ObjectId(String(v.entity)), + }; + } + + return v; + }) || [], + }), + }, + }, + // support pageQuery + { + $skip: pageQuery?.skip || 0, + }, + { + $limit: pageQuery?.limit || 10, + }, + { + $sort: { + [pageQuery?.sort?.[0] || 'createdAt']: + pageQuery?.sort?.[1] === 'desc' ? -1 : 1, + }, + }, + { + $lookup: { + from: 'nlpsampleentities', + localField: '_id', + foreignField: 'value', + as: 'sampleEntities', + }, + }, + { + $unwind: { + path: '$sampleEntities', + preserveNullAndEmptyArrays: true, + }, + }, + { + $lookup: { + from: 'nlpsamples', + localField: 'sampleEntities.sample', + foreignField: '_id', + as: 'samples', + }, + }, + { + $lookup: { + from: 'nlpentities', + localField: 'entity', + foreignField: '_id', + as: 'entities', + }, + }, + { + $group: { + _id: '$_id', + value: { $first: '$value' }, + expressions: { $first: '$expressions' }, + builtin: { $first: '$builtin' }, + metadata: { $first: '$metadata' }, + createdAt: { $first: '$createdAt' }, + updatedAt: { $first: '$updatedAt' }, + entity: { + // support populate + $first: populate.some((p) => + this.getPopulate() + .map((p) => p.toString()) + .includes(p), + ) + ? '$entities' + : '$entity', + }, + //TODO when samples is empty array we need to return 0 not 1 + nlpSamplesCount: { + $sum: { $cond: [{ $ifNull: ['samples', false] }, 1, 0] }, + }, + }, + }, + { + $project: { + id: '$_id', + _id: 0, + value: 1, + expressions: 1, + builtin: 1, + entity: 1, + metadata: 1, + createdAt: 1, + updatedAt: 1, + nlpSamplesCount: 1, + }, + }, + ]) + .exec(); + } } diff --git a/api/src/nlp/services/nlp-value.service.ts b/api/src/nlp/services/nlp-value.service.ts index c9ec6309..f4147333 100644 --- a/api/src/nlp/services/nlp-value.service.ts +++ b/api/src/nlp/services/nlp-value.service.ts @@ -7,7 +7,6 @@ */ import { forwardRef, Inject, Injectable } from '@nestjs/common'; -import { Types } from 'mongoose'; import { DeleteResult } from '@/utils/generics/base-repository'; import { BaseService } from '@/utils/generics/base-service'; @@ -229,115 +228,10 @@ export class NlpValueService extends BaseService< filters?: TFilterQuery, pageQuery?: PageQueryDto, ) { - const { $and = [], ...rest } = filters || ({} as TFilterQuery); - - const entityValueModel = this.getRepository().model; - - return entityValueModel - .aggregate([ - { - // support filters - $match: { - ...rest, - ...($and?.length && { - $and: - $and?.map((v) => { - if (v.entity) { - return { - ...v, - entity: new Types.ObjectId(String(v.entity)), - }; - } - - return v; - }) || [], - }), - }, - }, - // support pageQuery - { - $skip: pageQuery?.skip || 0, - }, - { - $limit: pageQuery?.limit || 10, - }, - { - $sort: { - [pageQuery?.sort?.[0] || 'createdAt']: - pageQuery?.sort?.[1] === 'desc' ? -1 : 1, - }, - }, - { - $lookup: { - from: 'nlpsampleentities', - localField: '_id', - foreignField: 'value', - as: 'sampleEntities', - }, - }, - { - $unwind: { - path: '$sampleEntities', - preserveNullAndEmptyArrays: true, - }, - }, - { - $lookup: { - from: 'nlpsamples', - localField: 'sampleEntities.sample', - foreignField: '_id', - as: 'samples', - }, - }, - { - $lookup: { - from: 'nlpentities', - localField: 'entity', - foreignField: '_id', - as: 'entities', - }, - }, - { - $group: { - _id: '$_id', - value: { $first: '$value' }, - expressions: { $first: '$expressions' }, - builtin: { $first: '$builtin' }, - metadata: { $first: '$metadata' }, - createdAt: { $first: '$createdAt' }, - updatedAt: { $first: '$updatedAt' }, - entity: { - // support populate - $first: populate.some((p) => - this.getRepository() - .getPopulate() - .map((p) => p.toString()) - .includes(p), - ) - ? '$entities' - : '$entity', - }, - //TODO when samples is empty array we need to return 0 not 1 - nlpSamplesCount: { - $sum: { $cond: [{ $ifNull: ['samples', false] }, 1, 0] }, - }, - }, - }, - { - $project: { - id: '$_id', - _id: 0, - value: 1, - expressions: 1, - builtin: 1, - entity: 1, - metadata: 1, - createdAt: 1, - updatedAt: 1, - nlpSamplesCount: 1, - }, - }, - ]) - .exec(); + return await this.repository.findAndPopulateNlpValuesWithCount( + populate, + filters, + pageQuery, + ); } }