Typeorm update record in OneToMany relation - postgresql

I have the following two entities with a OneToMany/ManyToOne relation between them:
#Entity({ name: 'user' })
export class User {
#PrimaryGeneratedColumn('increment')
id: number;
#Column({ type: 'varchar' })
firstName: string;
#Column({ type: 'varchar' })
lastName: string;
#ManyToOne(() => Group, group => group.id)
#JoinColumn({ name: 'groupId' })
group: Group;
#Column({ type: 'integer' })
groupId: number;
}
#Entity({ name: 'group' })
export class Group {
#PrimaryGeneratedColumn('increment')
id: number;
#Column({ type: 'varchar' })
name: string;
#OneToMany(() => User, user => user.group)
members: User[];
}
When I create a new group in my Group repository, I can add existing members as follows:
const group = new Group();
group.name = 'Test';
group.members = [{ id: 1 }, { id: 2 }]; // user ids
this.save(group);
I am wondering if I can update existing members in a similar way. For example if a group with id 1 has two members:
{ id: 1, firstName: 'Member', lastName: 'One', groupId: 1 }
{ id: 2, firstName: 'Member', lastName: 'Two', groupId: 1 }
Is it possible to update a member through the OneToMany relation in a similar way as I'm adding them ? Something like (making this up):
const group = await repository.findOne(groupId, { relations: ['members'] });
group.members = [{ id: 1, firstName: 'Updated' }]; // this would update the firstName of member with id 1 if it exists in the relation
repository.save(group);
Thanks!

There is no built in functionality in typeorm to update specific related entity from the base entity. However if you want to do this then you can add a general function which updates the base table as well as it's relations.

Related

How do I search in the postgresql using Typeorm and return the mutated value for relation?

I have a User entity with a Role relationship in an application Nestjs.
#Entity()
class User {
...
#ManyToOne(() => Role, {
eager: true,
})
role?: Role;
}
#Entity()
export class Role extends EntityHelper {
#PrimaryColumn()
id: number;
#Column()
name?: string;
}
when I want get users from the DB I do:
this.usersRepository.find({
relations: {
role: true,
},
})
and I get data like this:
{ id: 1, name: "John", role: { id: 2, name: "user" }}
but I don't want to get the role as an object, I just want the name from this
Example:
{ id: 1, name: "John", role: "user" }
So, my question is how can I get the relation and return only the value of { ... role: "user" }?
You can achieve it by using QueryBuilder:
this.usersRepository.createQueryBuilder('User')
.innerJoinAndSelect('User.role', 'Role')
.select(['Role.name as role', 'User.id as id'])
.getRawMany()

Nested populate not working for mikro-orm

I'm using mikro-orm with nest.js, I have Users, Roles and Permissions entities. I need to select user by id with it's role and permissions from database. I'm using the following code to select user with everything:
this._userRepo.findOne({ $or: [{ email }] }, { populate: ['role', 'role.permissions'] })
I need the result to look like the following code example, but permissions are not selected:
{
id: 1,
email: 'john.doe#inter.net',
firstName: 'john',
lastName: 'Doe',
...
role: {
id: 21,
name: 'Moderator',
permissions: [
{ id: 1, name: 'Create' },
{ id: 2, name: 'Update' },
{ id: 3, name: 'Delete' },
]
}
}
Here's how my entities and schema looks like:
// user.entity.ts
#Entity({ tableName: 'users' })
export class UserEntity {
#PrimaryKey() id: number;
#Property() email: string;
#Property() firstName: string;
#Property() lastName: string;
...
#ManyToOne(() => RoleEntity) role: ref<RoleEntity, 'id'>;
constructor(role: RoleEntity) {
this.role = ref(role);
}
}
// role.entity.ts
#Entity({ tableName: 'roles' })
export class RoleEntity {
#PrimaryKey() id: number;
#Property() name: string;
...
#ManyToMany(() => PermissionEntity) permissions = new Collection<PermissionEntity>(this);
}
// permission.entity.ts
#Entity({ tableName: 'permissions' })
export class PermissionEntity {
#PrimaryKey() id: number;
#Property() name: string;
}
And there's roles_permissions table generated in database:
|role_entity_id|permission_entity_id|
|--------------|--------------------|
| 1 | 1 |
How can I solve this issue?
After torturing for several hours, I found that I was missing some properties to be specified in #ManyToMany relation.
So, I changed my RoleEntity to:
#Entity({ tableName: 'roles' })
export class RoleEntity {
#PrimaryKey() id: number;
#Property() name: string;
...
#ManyToMany({
entity: () => PermissionEntity,
owner: true,
pivotTable: 'roles_permissions',
joinColumn: 'role_entity_id',
inverseJoinColumn: 'permission_entity_id',
hidden: true,
})
permissions = new Collection<PermissionEntity>(this);
}
And now I can select role with it's permissions from database.

How can I create a UUID FK column in NestJS?

I am running into an odd issue where I can't create a FK relationship between two entities.
// organization.entity.ts
#PrimaryGeneratedColumn('uuid')
id: string;
...
#OneToMany(() => User, (user) => user.organization)
users: User[];
// user.entity.ts
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({
type: 'uuid',
})
organizationId: string;
...
#ManyToOne(() => Organization, (organization) => organization.users)
organization: Organization;
In my ormconfig.json file I have these settings (among connection creds)
...
"logging": true,
"entities": [
"dist/**/*.entity{.ts,.js}"
],
"synchronize": true
...
I am using "typeorm": "^0.2.45" in my package.json file.
Key columns "organizationId" and "id" are of incompatible types: character varying and uuid.
How can I create an FK relationship between users & organizations?
So from your question I understood is you want a "organizationId" field in your users table which will be a FK.
To create OnetoMany Relation between Organization and users do as below:
// organization.entity.ts
#Entity({ name: 'organizations' })
export class Organization {
#PrimaryGeneratedColumn('uuid')
id: string;
...
#OneToMany(() => User, (user) => user.organization)
users: User[];
}
// user.entity.ts
#Entity({ name: 'users' })
export class User {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column({ type: 'uuid' })
organizationId: string;
...
#ManyToOne(() => Organization, (organization) => organization.users)
#JoinColumn({ name: 'organizationId' })
organization: Organization;
}

How to select data by using typeorm from 3 tables which depend on each other?

I have 3 entity which depend on each other and I have a problem with querying data from them by using one request.
First one User:
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column()
firstName: string;
#Column()
lastName: string;
#Column()
login: string;
#Column()
password: string;
#Column()
ownerId: number;
#OneToOne(() => Role, (role) => role.user)
#JoinColumn()
role?: Role;
}
Second one Role:
#Entity()
export class Role extends BaseEntity {
#PrimaryGeneratedColumn()
id: number;
#Column()
name: string;
#Column()
description: string;
#ManyToOne(() => User, (user) => user.role)
#JoinColumn()
user: User | null;
#ManyToMany(() => Permission, { cascade: true })
#JoinTable({ name: 'roles_has_permissions' })
permissions: Permission[];
}
Third one Permission:
#Entity()
export class Permission {
#PrimaryGeneratedColumn()
id: number;
#Column()
name: PossiblePermissions;
}
How to select data from database. I’m using typeorm with Postgresql and I want to get array like this.
[{
…user info by ownerId
role: {
…role which related this user
permissions: [{
…permissions which related this role
}, …]
}
}, …]
Use query builder https://typeorm.io/#/select-query-builder
In your case it should be something like this:
await connection
.getRepository(User)
.createQueryBuilder("user")
.leftJoinAndSelect("user.role", "role")
.leftJoinAndSelect("role.permissions", "permissions")
.getMany()

TypeORM - Query OneToMany related entities with TypeORM Repository

I just trying to query a OneToMany related entities but, in this query, i need to get eager loaded data from Entity2 with query in Entity1.
Example:
I have those entities:
//Entity1
#Entity('roles')
export class Role {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
title: string;
#OneToMany(() => User, user => user.role)
users: User[];
}
//Entity2
export class User {
#PrimaryGeneratedColumn('uuid')
id: string;
#Column()
name: string;
#Column('uuid')
role_id: string;
#ManyToOne(() => Role, role => role.users)
#JoinColumn({ name: 'role_id' })
role: Role;
}
So, im trying to make a query like this:
const rolesRepository = getRepository(Role);
rolesRepository.find({
where: {
// user's name
name: ILike("%john%")
},
relations: ['users']
});
I need to use user's name to find all roles who have users with name containing "John" and get role and user data (eager load) like:
Role: {
id: '6fa6fa8b-f0e1-48bf-b0ec-61eb35585eba',
title: 'Pathfinder',
users: [
{
id: 'c9097d7d-b83b-412b-9c81-6a918c07e360',
name: 'John Doe',
role_id: '6fa6fa8b-f0e1-48bf-b0ec-61eb35585eba'
},
{
id: 'ed1fffb0-dae5-46ce-83ce-38b379483c7f',
name: 'Johnny',
role_id: '6fa6fa8b-f0e1-48bf-b0ec-61eb35585eba'
}
]
}
I dont want to use { eager: true } in the entity because i just need one single query using eager loading (using in the entity i will have over-fetching).
This isn't working and i know it doesn't make sense to do a query that way. I just did it to understand the purpose.
Database: Postgres