Skip to content

Commit 09140ec

Browse files
authored
Merge pull request #45 from klerick/condition-by-reletion
fix(json-api-nestjs): try to fix condition
2 parents c8752fa + 478e0cd commit 09140ec

File tree

3 files changed

+156
-128
lines changed

3 files changed

+156
-128
lines changed

libs/json-api-nestjs/src/lib/mixin/service/typeorm/methods/get-all/get-all.ts

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,23 @@ export async function getAll<T>(
7171

7272
const { target, relation } = filter;
7373

74+
const expressionObjectForRelation = relation
75+
? this.UtilsMethode.applyQueryFilterRelation(
76+
builder,
77+
relation,
78+
this.repository.metadata
79+
)
80+
: [];
81+
7482
const expressionObject = [
7583
...(target
7684
? this.UtilsMethode.applyQueryFiltersTarget(
77-
builder,
78-
target,
79-
this.repository.metadata
80-
)
81-
: []),
82-
...(relation
83-
? this.UtilsMethode.applyQueryFilterRelation(
84-
builder,
85-
relation,
86-
this.repository.metadata
87-
)
85+
builder,
86+
target,
87+
this.repository.metadata
88+
)
8889
: []),
90+
...expressionObjectForRelation,
8991
];
9092
const expressionObjectLength = expressionObject.length;
9193
const includeLength = include ? include.length : 0;
@@ -168,10 +170,24 @@ export async function getAll<T>(
168170
.setParameters(builder.getParameters())
169171
.getRawMany<T>();
170172

171-
const result = await resultBuilderQuery
173+
const resultBuilder = resultBuilderQuery
172174
.select([...fieldsSelect])
173-
.whereInIds(resultIds.map((i) => i[`${countAlias}_${primaryColumn}`]))
174-
.getRawMany();
175+
.whereInIds(resultIds.map((i) => i[`${countAlias}_${primaryColumn}`]));
176+
177+
for (let i = 0; i < expressionObjectForRelation.length; i++) {
178+
const { expression, params, selectInclude } =
179+
expressionObjectForRelation[i];
180+
if (selectInclude) {
181+
resultBuilder.leftJoin(
182+
`${preparedResourceName}.${selectInclude}`,
183+
selectInclude
184+
);
185+
}
186+
resultBuilder.andWhere(expression);
187+
resultBuilder.setParameters(params ? { [params.name]: params.val } : {});
188+
}
189+
190+
const result = await resultBuilder.getRawMany();
175191

176192
const callQuery = Date.now() - startTime;
177193

libs/json-api-nestjs/src/lib/mixin/service/typeorm/utils/utils-methode.spec.ts

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ describe('Utils methode test', () => {
268268
isActive: { [FilterOperand.gte]: 'test' },
269269
lastName: { [FilterOperand.in]: ['test', 'test'] },
270270
createdAt: { [FilterOperand.like]: 'test' },
271-
updatedAt: { [FilterOperand.lt]: 'test' },
271+
updatedAt: { [FilterOperand.lt]: 'test', [FilterOperand.gt]: 'test' },
272272
id: { [FilterOperand.lte]: 'test' },
273273
},
274274
};
@@ -306,30 +306,34 @@ describe('Utils methode test', () => {
306306
);
307307

308308
const params = Object.keys(filter.manager);
309+
let increment = 0;
309310
for (let i = 0; i < params.length; i++) {
310311
const alias = 'manager';
311-
const paramsName = UtilsMethode.getParamName(
312-
`${alias}.${params[i]}`,
313-
i
314-
);
315-
const operand = Object.keys(filter.manager[params[i]])[0];
316-
const checkExpression = OperandsMap[operand].replace(
317-
'EXPRESSION',
318-
paramsName
319-
);
320-
expect(expression[i].expression).toBe(
321-
`${alias}.${params[i]} ${checkExpression}`
322-
);
323-
expect(expression[i].params.name).toBe(paramsName);
324-
if (operand === FilterOperand.like) {
325-
expect(expression[i].params.val).toBe(
326-
`%${filter.manager[params[i]][operand]}%`
312+
for (const operand of Object.keys(filter.manager[params[i]])){
313+
const paramsName = UtilsMethode.getParamName(
314+
`${alias}.${params[i]}`,
315+
increment
327316
);
328-
} else {
329-
expect(expression[i].params.val).toBe(
330-
filter.manager[params[i]][operand]
317+
const checkExpression = OperandsMap[operand].replace(
318+
'EXPRESSION',
319+
paramsName
331320
);
321+
expect(expression[increment].expression).toBe(
322+
`${alias}.${params[i]} ${checkExpression}`
323+
);
324+
expect(expression[increment].params.name).toBe(paramsName);
325+
if (operand === FilterOperand.like) {
326+
expect(expression[increment].params.val).toBe(
327+
`%${filter.manager[params[i]][operand]}%`
328+
);
329+
} else {
330+
expect(expression[increment].params.val).toBe(
331+
filter.manager[params[i]][operand]
332+
);
333+
}
334+
increment++
332335
}
336+
333337
expect(expression[i].selectInclude).toBe('manager');
334338
}
335339

libs/json-api-nestjs/src/lib/mixin/service/typeorm/utils/utils-methode.ts

Lines changed: 102 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ export class UtilsMethode {
143143
resultExpression.push({
144144
expression: `${preparedResourceName}.${field.toString()} ${OperandMapForNull[
145145
operand
146-
].replace(
146+
].replace(
147147
'EXPRESSION',
148148
UtilsMethode.getParamName(
149149
`${preparedResourceName}.${field}`,
@@ -158,7 +158,7 @@ export class UtilsMethode {
158158
resultExpression.push({
159159
expression: `${preparedResourceName}.${field.toString()} ${OperandsMap[
160160
operand
161-
].replace(
161+
].replace(
162162
'EXPRESSION',
163163
UtilsMethode.getParamName(`${preparedResourceName}.${field}`, i)
164164
)}`,
@@ -203,110 +203,118 @@ export class UtilsMethode {
203203
const resourceName = snakeToCamel(name);
204204
let relationFieldProperty: keyof Filter<T>['relation'][typeof relationProperty];
205205
for (relationFieldProperty in filter[relationProperty]) {
206-
const operand = Object.keys(
206+
for (const operand of Object.keys(
207207
filter[relationProperty][relationFieldProperty]
208-
).pop();
209-
const value =
210-
operand === FilterOperand.like
211-
? `%${filter[relationProperty][relationFieldProperty][operand]}%`
212-
: filter[relationProperty][relationFieldProperty][operand];
213-
214-
const currentOperandMap =
215-
value.toString().toLocaleLowerCase() === 'null'
216-
? OperandMapForNull
217-
: OperandsMap;
218-
const paramsField =
219-
value.toString().toLocaleLowerCase() === 'null'
220-
? null
221-
: UtilsMethode.getParamName(
208+
)) {
209+
const value =
210+
operand === FilterOperand.like
211+
? `%${filter[relationProperty][relationFieldProperty][operand]}%`
212+
: filter[relationProperty][relationFieldProperty][operand];
213+
const currentOperandMap =
214+
value.toString().toLocaleLowerCase() === 'null'
215+
? OperandMapForNull
216+
: OperandsMap;
217+
const paramsField =
218+
value.toString().toLocaleLowerCase() === 'null'
219+
? null
220+
: UtilsMethode.getParamName(
222221
`${relationProperty}.${relationFieldProperty.toString()}`,
223222
i
224223
);
225-
switch (relation.relationType) {
226-
case 'many-to-many': {
227-
const { inverseJoinColumns, joinColumns } =
228-
relation.isManyToManyOwner ? relation : relation.inverseRelation;
229-
const relationProps = relation.isManyToManyOwner
230-
? relation
231-
: relation.inverseRelation;
232-
const { joinTableName } = relationProps;
233-
const { databaseName: queryJoinPropsName } =
234-
relation.isManyToManyOwner
235-
? inverseJoinColumns[0]
236-
: joinColumns[0];
237-
const { databaseName: selectJoinPropsName } =
238-
relation.isManyToManyOwner
239-
? joinColumns[0]
240-
: inverseJoinColumns[0];
241-
const onQuery = `${joinTableName}.${queryJoinPropsName} = ${relationProperty}.${primaryColumn}`;
242-
const selectQuery = `${joinTableName}.${selectJoinPropsName}`;
243-
244-
const query = builder
245-
.subQuery()
246-
.select(selectQuery)
247-
.from(joinTableName, joinTableName)
248-
.leftJoin(resourceName, relationProperty, onQuery)
249-
.where(
250-
`${relationProperty}.${relationFieldProperty.toString()} ${currentOperandMap[
251-
operand
252-
].replace('EXPRESSION', paramsField)}`
253-
)
254-
.getQuery();
255-
resultExpression.push({
256-
expression: `${preparedResourceName}.id IN ${query}`,
257-
params:
258-
paramsField === null
259-
? null
260-
: {
224+
switch (relation.relationType) {
225+
case 'many-to-many': {
226+
const { inverseJoinColumns, joinColumns } =
227+
relation.isManyToManyOwner
228+
? relation
229+
: relation.inverseRelation;
230+
const relationProps = relation.isManyToManyOwner
231+
? relation
232+
: relation.inverseRelation;
233+
const { joinTableName } = relationProps;
234+
const { databaseName: queryJoinPropsName } =
235+
relation.isManyToManyOwner
236+
? inverseJoinColumns[0]
237+
: joinColumns[0];
238+
const { databaseName: selectJoinPropsName } =
239+
relation.isManyToManyOwner
240+
? joinColumns[0]
241+
: inverseJoinColumns[0];
242+
const onQuery = `${joinTableName}.${queryJoinPropsName} = ${relationProperty}.${primaryColumn}`;
243+
const selectQuery = `${joinTableName}.${selectJoinPropsName}`;
244+
245+
const query = builder
246+
.subQuery()
247+
.select(selectQuery)
248+
.from(joinTableName, joinTableName)
249+
.leftJoin(resourceName, relationProperty, onQuery)
250+
.where(
251+
`${relationProperty}.${relationFieldProperty.toString()} ${currentOperandMap[
252+
operand
253+
].replace('EXPRESSION', paramsField)}`
254+
)
255+
.getQuery();
256+
resultExpression.push({
257+
expression: `${preparedResourceName}.id IN ${query}`,
258+
params:
259+
paramsField === null
260+
? null
261+
: {
261262
val: value,
262263
name: paramsField,
263264
},
264-
});
265+
});
265266

266-
break;
267-
}
268-
case 'one-to-many': {
269-
const query = builder
270-
.subQuery()
271-
.select(`${resourceName}.${inverseSidePropertyPath}`)
272-
.from(target, resourceName)
273-
.where(
274-
`${resourceName}.${relationFieldProperty.toString()} ${currentOperandMap[
267+
break;
268+
}
269+
case 'one-to-many': {
270+
if (paramsField !== null) {
271+
resultExpression.push({
272+
expression: `${relationProperty}.${relationFieldProperty.toString()} ${currentOperandMap[
273+
operand
274+
].replace('EXPRESSION', paramsField)}`,
275+
params: {
276+
val: value,
277+
name: paramsField,
278+
},
279+
selectInclude: relationProperty,
280+
});
281+
break;
282+
}
283+
const query = builder
284+
.subQuery()
285+
.select(`${resourceName}.${inverseSidePropertyPath}`)
286+
.from(target, resourceName)
287+
.where(
288+
`${resourceName}.${relationFieldProperty.toString()} ${currentOperandMap[
289+
operand
290+
].replace('EXPRESSION', paramsField)}`
291+
)
292+
.getQuery();
293+
resultExpression.push({
294+
expression: `${preparedResourceName}.id IN ${query}`,
295+
params: null,
296+
});
297+
break;
298+
}
299+
default:
300+
resultExpression.push({
301+
expression: `${relationProperty}.${relationFieldProperty.toString()} ${currentOperandMap[
275302
operand
276-
].replace('EXPRESSION', paramsField)}`
277-
)
278-
.getQuery();
279-
280-
resultExpression.push({
281-
expression: `${preparedResourceName}.id IN ${query}`,
282-
params:
283-
paramsField === null
284-
? null
285-
: {
303+
].replace('EXPRESSION', paramsField)}`,
304+
params:
305+
paramsField === null
306+
? null
307+
: {
286308
val: value,
287309
name: paramsField,
288310
},
289-
});
290-
break;
311+
selectInclude: relationProperty,
312+
});
313+
break;
291314
}
292-
default:
293-
resultExpression.push({
294-
expression: `${relationProperty}.${relationFieldProperty.toString()} ${currentOperandMap[
295-
operand
296-
].replace('EXPRESSION', paramsField)}`,
297-
params:
298-
paramsField === null
299-
? null
300-
: {
301-
val: value,
302-
name: paramsField,
303-
},
304-
selectInclude: relationProperty,
305-
});
306-
break;
307-
}
308315

309-
i++;
316+
i++;
317+
}
310318
}
311319
}
312320
return resultExpression;
@@ -380,8 +388,8 @@ export class UtilsMethode {
380388
) {
381389
const detail = isArray
382390
? `Resource '${relationsTypeName}' with ids '${idsToAdd.join(
383-
','
384-
)}' does not exist`
391+
','
392+
)}' does not exist`
385393
: `Resource '${relationsTypeName}' with id '${idsToAdd[0]}' does not exist`;
386394
throw new NotFoundException({
387395
detail,

0 commit comments

Comments
 (0)