Skip to content

Commit 72dd210

Browse files
authored
Merge pull request #28 from Diluka/feature/deep-relations
nested relations query
2 parents e255120 + 01fcd9a commit 72dd210

16 files changed

+348
-30
lines changed

README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,8 @@ _Syntax:_
314314
315315
> ?join=**relation**||**field1**,**field2**,...
316316
317+
> ?join=**relation1**||**field11**,**field12**,...&join=**relation1**.**relation2**||**field21**,**field22**,...&join=...
318+
317319
_Examples:_
318320

319321
> ?join=**profile**
@@ -322,7 +324,9 @@ _Examples:_
322324
323325
> ?join=**profile**||**firstName**,**email**&join=**notifications**||**content**&join=**tasks**
324326
325-
**_Notice:_** `id` field always persists in relational objects.
327+
> ?join=**relation1**&join=**relation1**.**relation2**&join=**relation1**.**relation2**.**relation3**
328+
329+
**_Notice:_** `id` field always persists in relational objects. To use nested relations, the parent level **MUST** be set before the child level like example above.
326330

327331
_Alias:_ `join[]`
328332

@@ -476,7 +480,8 @@ An Object of [relations](http://typeorm.io/#/relations) that allowed to be fetch
476480
notifications: {
477481
exclude: ['token']
478482
},
479-
company: {}
483+
company: {},
484+
'company.projects': {}
480485
}
481486
}
482487
```

integration/typeorm/e2e/company.entity.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { CrudValidate } from '../../../src/';
44

55
import { BaseEntity } from '../src/base-entity';
66
import { User } from './user.entity';
7+
import { Project } from './project.entity';
8+
import { Task } from './task.entity';
79

810
const { CREATE, UPDATE } = CrudValidate;
911

@@ -34,4 +36,10 @@ export class Company extends BaseEntity {
3436

3537
@OneToMany((type) => User, (u) => u.company)
3638
users: User[];
39+
40+
@OneToMany((type) => Project, (p) => p.company)
41+
projects: Project[];
42+
43+
@OneToMany((type) => Task, (t) => t.company)
44+
tasks: Task[];
3745
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright under the Parsec Tech Co., Ltd. Version 1.0;
3+
* you may not use this file except in compliance with the permit.
4+
* Copyright (c) 2019 ChongQing Parsec Technology Corporation. All Rights Reserved.
5+
* Version 1.0
6+
*/
7+
8+
import { Entity, Column, ManyToOne, ManyToMany, OneToMany, JoinTable } from 'typeorm';
9+
import { BaseEntity } from '../src/base-entity';
10+
import { Company } from './company.entity';
11+
import { User } from './user.entity';
12+
import { Task } from './task.entity';
13+
14+
@Entity('projects')
15+
export class Project extends BaseEntity {
16+
@Column({ type: 'varchar', length: 100, nullable: false, unique: true })
17+
name: string;
18+
19+
@Column({ type: 'text', nullable: true })
20+
description: string;
21+
22+
@Column({ nullable: false })
23+
companyId: number;
24+
25+
/**
26+
* Relations
27+
*/
28+
29+
@ManyToOne((type) => Company, (c) => c.projects)
30+
company: Company;
31+
32+
@ManyToMany((type) => User, (u) => u.projects, { cascade: true })
33+
@JoinTable()
34+
users: User[];
35+
36+
@OneToMany((type) => Task, (t) => t.project)
37+
tasks: Task[];
38+
}

integration/typeorm/e2e/seeds.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,93 @@ export class Seeds1544303473346 implements MigrationInterface {
6666
('[email protected]', '9c81f2857e8f', false, 2, 19),
6767
('[email protected]', '9c81f2857e8f', false, 2, 20);
6868
`);
69+
70+
// projects
71+
await queryRunner.query(`
72+
INSERT INTO public.projects ("name", "description", "companyId")
73+
VALUES ('project1', 'project 1 desc', 1),
74+
('project2', 'project 2 desc', 1),
75+
('project3', 'project 3 desc', 1),
76+
('project4', 'project 4 desc', 1),
77+
('project5', 'project 5 desc', 1),
78+
('project6', 'project 6 desc', 1),
79+
('project7', 'project 7 desc', 1),
80+
('project8', 'project 8 desc', 1),
81+
('project9', 'project 9 desc', 2),
82+
('project10', 'project 10 desc', 3),
83+
('project11', 'project 11 desc', 4),
84+
('project12', 'project 12 desc', 5),
85+
('project13', 'project 13 desc', 6),
86+
('project14', 'project 14 desc', 7),
87+
('project15', 'project 15 desc', 8),
88+
('project16', 'project 16 desc', 9);
89+
`);
90+
91+
// tasks
92+
await queryRunner.query(`
93+
INSERT INTO public.tasks ("name", "status", "companyId", "projectId", "userId")
94+
VALUES ('task11', 'a', 1, 1, 1),
95+
('task12', 'a', 1, 1, 1),
96+
('task13', 'a', 1, 1, 1),
97+
('task14', 'a', 1, 1, 1),
98+
('task21', 'a', 1, 2, 2),
99+
('task22', 'a', 1, 2, 2),
100+
('task23', 'a', 1, 2, 2),
101+
('task24', 'a', 1, 2, 2),
102+
('task31', 'a', 1, 3, 3),
103+
('task32', 'a', 1, 3, 3),
104+
('task33', 'a', 1, 3, 3),
105+
('task34', 'a', 1, 3, 3),
106+
('task41', 'a', 1, 4, 4),
107+
('task42', 'a', 1, 4, 4),
108+
('task43', 'a', 1, 4, 4),
109+
('task44', 'a', 1, 4, 4),
110+
('task1', 'a', 1, 1, 5),
111+
('task2', 'a', 1, 1, 5),
112+
('task3', 'a', 1, 1, 5),
113+
('task4', 'a', 1, 1, 5),
114+
('task1', 'a', 1, 1, 6),
115+
('task2', 'a', 1, 1, 6),
116+
('task3', 'a', 1, 1, 6),
117+
('task4', 'a', 1, 1, 6),
118+
('task1', 'a', 1, 1, 7),
119+
('task2', 'a', 1, 1, 7),
120+
('task3', 'a', 1, 1, 7),
121+
('task4', 'a', 1, 1, 7);
122+
`);
123+
124+
// user projects
125+
await queryRunner.query(`
126+
INSERT INTO public.projects_users_users ("projectsId", "usersId")
127+
VALUES (1, 1),
128+
(1, 2),
129+
(1, 3),
130+
(1, 4),
131+
(1, 5),
132+
(1, 6),
133+
(1, 7),
134+
(1, 8),
135+
(1, 9),
136+
(2, 1),
137+
(2, 2),
138+
(2, 3),
139+
(2, 4),
140+
(2, 5),
141+
(2, 6),
142+
(2, 7),
143+
(2, 8),
144+
(2, 9);
145+
`);
69146
}
70147

71148
public async down(queryRunner: QueryRunner): Promise<any> {
72149
// flush
150+
await queryRunner.query(
151+
`DELETE FROM public.tasks; ALTER SEQUENCE tasks_id_seq RESTART WITH 1;`,
152+
);
153+
await queryRunner.query(
154+
`DELETE FROM public.projects; ALTER SEQUENCE projects_id_seq RESTART WITH 1;`,
155+
);
73156
await queryRunner.query(
74157
`DELETE FROM public.users; ALTER SEQUENCE users_id_seq RESTART WITH 1;`,
75158
);
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright under the Parsec Tech Co., Ltd. Version 1.0;
3+
* you may not use this file except in compliance with the permit.
4+
* Copyright (c) 2019 ChongQing Parsec Technology Corporation. All Rights Reserved.
5+
* Version 1.0
6+
*/
7+
8+
import { Entity, Column, ManyToOne } from 'typeorm';
9+
import { BaseEntity } from '../src/base-entity';
10+
import { Company } from './company.entity';
11+
import { Project } from './project.entity';
12+
import { User } from './user.entity';
13+
14+
@Entity('tasks')
15+
export class Task extends BaseEntity {
16+
@Column({ type: 'varchar', length: 100, nullable: false })
17+
name: string;
18+
19+
@Column({ type: 'varchar', nullable: false })
20+
status: string;
21+
22+
@Column({ nullable: false })
23+
companyId: number;
24+
25+
@Column({ nullable: false })
26+
projectId: number;
27+
28+
@Column({ nullable: false })
29+
userId: number;
30+
31+
/**
32+
* Relations
33+
*/
34+
35+
@ManyToOne((type) => Company, (c) => c.tasks)
36+
company: Company;
37+
38+
@ManyToOne((type) => Project, (c) => c.tasks)
39+
project: Project;
40+
41+
@ManyToOne((type) => User, (u) => u.tasks)
42+
user: User;
43+
}

integration/typeorm/e2e/user.entity.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Entity, Column, JoinColumn, OneToOne, ManyToOne } from 'typeorm';
1+
import { Entity, Column, JoinColumn, OneToOne, ManyToOne, ManyToMany, OneToMany } from 'typeorm';
22
import {
33
IsOptional,
44
IsString,
@@ -11,9 +11,11 @@ import {
1111
import { Type } from '../../../node_modules/class-transformer';
1212
import { CrudValidate } from '../../../src/';
1313

14-
import { BaseEntity } from '../src//base-entity';
14+
import { BaseEntity } from '../src/base-entity';
1515
import { UserProfile } from './user-profile.entity';
1616
import { Company } from './company.entity';
17+
import { Project } from './project.entity';
18+
import { Task } from './task.entity';
1719

1820
const { UPDATE, CREATE } = CrudValidate;
1921

@@ -60,4 +62,10 @@ export class User extends BaseEntity {
6062

6163
@ManyToOne((type) => Company, (c) => c.users)
6264
company: Company;
65+
66+
@ManyToMany((type) => Project, (c) => c.users)
67+
projects: Project[];
68+
69+
@OneToMany((type) => Task, (t) => t.user)
70+
tasks: Task[];
6371
}

jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('./jest.config.json');
File renamed without changes.

package-lock.json

Lines changed: 60 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)