Skip to content

Commit

Permalink
fix: sub objects in mongoose are resolved
Browse files Browse the repository at this point in the history
  • Loading branch information
iamkhalidbashir committed Sep 21, 2023
1 parent dddced2 commit 27db7ee
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 9 deletions.
17 changes: 10 additions & 7 deletions packages/query-graphql/src/types/query/filter.type.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Field, InputType } from '@nestjs/graphql'
import { Field, InputType, TypeMetadataStorage } from '@nestjs/graphql'
import { Class, Filter, MapReflector } from '@ptc-org/nestjs-query-core'
import { Type } from 'class-transformer'
import { ValidateNested } from 'class-validator'
Expand Down Expand Up @@ -103,12 +103,15 @@ function getOrCreateFilterType<T>(

const { baseName } = getDTONames(TClass)
fields.forEach(({ propertyName, target, advancedOptions, returnTypeFunc }) => {
const FC = createFilterComparisonType({
FieldType: target,
fieldName: `${baseName}${upperCaseFirst(propertyName)}`,
allowedComparisons: advancedOptions?.allowedComparisons,
returnTypeFunc
})
const objectTypeMetadata = TypeMetadataStorage.getObjectTypeMetadataByTarget(target)
const FC = objectTypeMetadata
? getOrCreateFilterType(target, typeName, suffix, depth)
: createFilterComparisonType({
FieldType: target,
fieldName: `${baseName}${upperCaseFirst(propertyName)}`,
allowedComparisons: advancedOptions?.allowedComparisons,
returnTypeFunc
})
const nullable = advancedOptions?.filterRequired !== true
ValidateNested()(GraphQLFilter.prototype, propertyName)
if (advancedOptions?.filterRequired) {
Expand Down
37 changes: 35 additions & 2 deletions packages/query-mongoose/src/query/where.builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ export class WhereBuilder<Entity extends Document> {
* @param filter - the filter to build the WHERE clause from.
*/
build(filter: Filter<Entity>): FilterQuery<Entity> {
const { and, or } = filter
const normalizedFilter = this.getNormalizedFilter(filter)
const { and, or } = normalizedFilter
let ands: FilterQuery<Entity>[] = []
let ors: FilterQuery<Entity>[] = []
let filterQuery: FilterQuery<Entity> = {}
Expand All @@ -28,7 +29,7 @@ export class WhereBuilder<Entity extends Document> {
if (or && or.length) {
ors = or.map((f) => this.build(f))
}
const filterAnds = this.filterFields(filter)
const filterAnds = this.filterFields(normalizedFilter)
if (filterAnds) {
ands = [...ands, filterAnds]
}
Expand All @@ -41,6 +42,38 @@ export class WhereBuilder<Entity extends Document> {
return filterQuery
}

/**
* Normalizes a filter to a dot notation filter for objects with sub objects.
* @param filter - the filter to normalize.
* @private
*/
private getNormalizedFilter(filter: Filter<Entity>): Filter<Entity> {
if (!this.isGraphQLFilter(filter)) return filter
const newFilter = {}
const keys = Object.keys(filter)
// Converting to dot notation
for (const key of keys) {
const value = filter[key]
if (!['and', 'or'].includes(key) && this.isGraphQLFilter(value)) {
const subFilter = this.getNormalizedFilter(value as Filter<Entity>)
for (const subKey of Object.keys(subFilter)) {
newFilter[`${key}.${subKey}`] = subFilter[subKey]
}
} else {
newFilter[key] = value
}
}
return newFilter
}

/**
* Checks if a filter is a GraphQLFilter.
* @param filter - the filter to check.
* @private
*/
private isGraphQLFilter = (filter: unknown) =>
typeof filter === `object` && !Array.isArray(filter) && filter?.constructor?.name === 'GraphQLFilter'

/**
* Creates field comparisons from a filter. This method will ignore and/or properties.
* @param filter - the filter with fields to create comparisons for.
Expand Down

0 comments on commit 27db7ee

Please sign in to comment.