I have a ManyToMany relation between two entities and I don't know how can I Get data from the join table "device_users_user"
#Entity()
export class Device{
#PrimaryColumn()
Name:string;
#Column({ nullable: true})
Port:number;
#Column({ nullable: true})
IPadress:string;
#Column({ nullable: true})
Location:string;
#ManyToMany(type => User)
#JoinTable()
users: User[];
}
#Entity()
export class User{
#PrimaryColumn()
Id:number;
#Column({ nullable: true})
Departement:string;
#Column({ nullable: true})
FirstName:string;
#Column({ nullable: true})
LastName:string;
#Column({ nullable: true})
CardNumber:string;
#Column({ nullable: true})
MobilePhone:string;
}
You cannot query the join table directly, using the TypeORM API's (unless you try to do a raw query, but I assume this is not what you want to achieve... And I don't recommend it, as table names might be changed...).
However, as you declared the relation using #ManyToMany, you can load the users of your devices with a Query Builder, for instance:
const devicesWithUsers = await deviceRepository.createQueryBuilder('device')
.leftJoin('device.users', 'user')
.where(/* whatever you need */)
.getMany();
The documentation of TypeORM gives more examples, e.g.:
const user = await createQueryBuilder("user")
.leftJoinAndSelect("user.photos", "photo")
.where("user.name = :name", { name: "Timber" })
.getOne();
which could gives, as a result:
{
id: 1,
name: "Timber",
photos: [{
id: 1,
url: "me-with-chakram.jpg"
}, {
id: 2,
url: "me-with-trees.jpg"
}]
}
Related
I have two entities to create in the table, one for the user and the other to store the token, and when creating a user I need both to be filled in, but I don't know how to do that via the ORM of TYPEORM, how would you do a create?
UserEntity
#Entity('Users')
export class UserEntity {
#ObjectIdColumn()
_id: ObjectId;
#Column({ type: 'string', length: 24 })
name: string;
#Column({ type: 'string', length: 55 })
password: string;
#Column({ type: 'string', length: 24 })
email: string;
#Column({ type: 'number', length: 24 })
celphone: number;
#OneToOne(() => TokenEntity, (TokenEntity) => TokenEntity.user, {
cascade: true,
})
#JoinColumn()
token: TokenEntity;
#CreateDateColumn()
created_at: Date;
#UpdateDateColumn()
updated_at: Date;
}
TokenEntity
#Entity('UserTokens')
export class TokenEntity {
#ObjectIdColumn()
_id: ObjectId;
#OneToOne(() => UserEntity, (user) => user.token)
user: UserEntity;
#Column({ type: 'string', length: '100' })
accessToken: string;
#Column({ type: 'number' })
expereIn: number;
}
UPDATED ---
code repo
export class CreateUserRepo implements ICreateUserContract {
constructor(private menagerRepo: EntityManager) {}
public async create({
user,
token,
}: ICreateUserContract.Input): Promise<void> {
const createUserByToken = new TokenEntity();
createUserByToken.accessToken = token.accessToken;
createUserByToken.expereIn = token.expireIn;
const createUser = new UserEntity();
createUser.name = user.name;
createUser.password = user.password;
createUser.celphone = user.celphone;
createUser.email = user.email;
createUser.token = createUserByToken;
await this.menagerRepo.save(createUser);
}
}
----- Updated
it is saving in both as expected, but in the User document it is saving a Token column, with token info, but I don't want that, I want a connection only, not to save the information in the same document...
As far as I understand, what you want is a bi-directional relation, which is described by typeorm. You attempted that with the inverse sides (UserEntity) => UserEntity.id and (TokenEntity) => TokenEntity.id. However, you want to access UserEntity and TokenEntity respectively, not their id. Change the accessors to (TokenEntity) => TokenEntity.user and (UserEntity) => UserEntity.tokenId, as they are declared in their classes.
I have two entities, users and roleuser, I have one to many mapping from user to role and many to one on user. while I am querying the result set, I am getting error as cannot read property joincolumns of undefined.Could anyone help me in solving this error, what am I doing wrong
Here are my entities.
// mosaique_user
#Entity()
export class MosaiqueUser {
#PrimaryGeneratedColumn()
id: number;
#Column({nullable: true, length: 100})
name: string;
#Column({unique: true, length: 255})
email: string;
#Column({nullable: true})
password: string;
#Column({nullable: true})
is_temp: number;
#Column({nullable: true})
salt: string;
#Column({nullable: true, default: 2})
status: number;
#Column({nullable: true, default: 2})
apply_status: number;
#Column({ type: 'timestamp', nullable: true})
created_at: Date;
#Column({ type: 'timestamp', nullable: true})
updated_at: Date;
#Column({ nullable: true})
created_by: number;
#Column({ nullable: true})
updated_by: number;
#OneToOne(() => MosaiqueUserProfile, userprofile => userprofile.user)
userprofile: MosaiqueUserProfile;
#OneToMany(() => RoleUser, userRole => userRole.user_id, {
cascade: true,
onDelete: 'CASCADE',
onUpdate: 'CASCADE',
})
#JoinColumn({ referencedColumnName: 'user_id' })
userRoles!: RoleUser[];
}
// role_user
#Entity()
export class RoleUser {
#PrimaryGeneratedColumn()
id: number;
#Column()
user_id: number;
#Column()
role_id: number;
#CreateDateColumn()
created_at: Date;
#UpdateDateColumn()
updated_at: Date;
#ManyToOne(() => MosaiqueUser, user => user.userRoles)
#JoinColumn({ name: 'user_id' })
user!: MosaiqueUser;
#ManyToOne(() => MRole, role => role.userRoles)
#JoinColumn({ name: 'role_id' })
role!: MRole;
}
// with relations query
let userData = await this.mosaiqueUser.find({
relations: ['userRoles'],
where: {'id':1}
});
Error
(node:57872) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'joinColumns' of undefined
at C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:1549:61
at Array.map ()
at SelectQueryBuilder.createJoinExpression (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:1520:57)
at SelectQueryBuilder.getQuery (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:57:21)
at SelectQueryBuilder.QueryBuilder.getQueryAndParameters (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\QueryBuilder.ts:446:28)
at SelectQueryBuilder. (C:\Sites\Dynamodb\TypeORMProject\src\query-builder\SelectQueryBuilder.ts:2112:40)
at step (C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:144:27)
at Object.next (C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:125:57)
at C:\Sites\Dynamodb\TypeORMProject\node_modules\tslib\tslib.js:118:75
at new Promise ()
I'm trying to make a POST-request and getting this error
{
"msg": "insert or update on table "client" violates foreign key constraint "FK_e61c5ecfaabf7e6d9285fbfb070""
}
My Client entity:
#Entity()
export default class Client extends BaseEntity {
#PrimaryGeneratedColumn()
clientId: number;
#Column({ type: 'enum', enum: ClientStatus, default: ClientStatus.NOT_CLIENT })
clientStatus: ClientStatus;
#Column({ nullable: true })
countryOfResidence: string;
#Column({ nullable: true, length: 30 })
firstName: string;
#Column({ nullable: true, length: 30 })
lastName: string;
#Column({ nullable: true, length: 30 })
surName: string;
#OneToOne(() => Passport)
#JoinColumn({ referencedColumnName: 'passportId', name: 'passportId' })
passportId: string;
#OneToOne(() => AuthVerification)
#JoinColumn({ referencedColumnName: 'mobilePhone', name: 'mobilePhone' })
mobilePhone: string;
#OneToOne(() => UserProfile, (userProfile) => userProfile.clientId)
userProfile: UserProfile;
}
My AuthVerification entity:
#Entity()
class AuthVerification extends BaseEntity {
#PrimaryColumn()
#OneToOne(() => Client)
mobilePhone: string;
#Column({ nullable: true })
email: string;
#Column({ nullable: false, length: 6 })
verificationCode: string;
}
Line in migration where constraint key mentioned:
await queryRunner.query(
`ALTER TABLE "client" ADD CONSTRAINT "FK_e61c5ecfaabf7e6d9285fbfb070" FOREIGN KEY ("mobilePhone") REFERENCES "auth_verification"("mobilePhone") ON DELETE NO ACTION ON UPDATE NO ACTION`
);
So, I can't figure out where the problem is.
For learning, I made a project testing out TypeGraphql, together with TypeORM. I have a User and Book entity, where I want to have a created_by field on the Book entity.
#ObjectType()
#Entity()
export class Book extends BaseEntity {
#Field(() => ID)
#PrimaryGeneratedColumn()
readonly id: number;
#Field({ nullable: true })
#Column({ nullable: true })
name: string;
#Field(() => User)
#ManyToOne(() => User)
#JoinColumn({ name: 'created_by' })
created_by: User;
// #RelationId((orthodontist: Orthodontist) => orthodontist.created_by)
// createdById: number;
}
#ObjectType()
#Entity()
export class User extends BaseEntity {
#Field(() => ID)
#PrimaryGeneratedColumn()
id: number;
#Field({ nullable: true })
#Column({ nullable: true })
first_name?: string;
#Field({ nullable: true })
#Column({ nullable: true })
last_name?: string;
#Field()
#Column({ unique: true })
email: string;
#Column()
password: string;
#Field(() => [Book!])
#OneToMany(() => Book, book => book.created_by)
created_books: Book[];
}
For my resolver, it simply looks like this, which I am properly loading as the docs say.
#Resolver(Book)
export class OrthodontistResolver {
#Query(() => [Book])
books(): Promise<Book[]> {
return Book.find();
}
}
When I go into my GraphQL playground, and query something like this:
{
books {
name,
id,
}
}
It all works and returns the right data. However, when I try to use the created_by field like this:
{
orthodontists {
name,
id,
created_by {
id
}
}
}
It gives me the following error:
Cannot return null for non-nullable field Book.created_by.
I made sure the relation exists in the database, and set up correctly with it's FK's. Where does this come from though? How can I fix this? I did try using the #RelationId decorator, as seen in the first code example. It unfortunately didn't work.
EDIT:
There is only one book in the database, where the created_by field is not null.
Change your books resolver to return the relationship created_by when using find operation:
#Resolver(Book)
export class OrthodontistResolver {
#Query(() => [Book])
books(): Promise<Book[]> {
return Book.find({
relations: ["created_by"],
});
}
}
Hi i have a relation between 'rooms' and 'room-servers'
RoomServers:
#Entity({ name: 'room-servers' })
export class RoomServer {
#PrimaryGeneratedColumn()
id: number;
#CreateDateColumn()
createdAt: Date;
#UpdateDateColumn()
updatedAt: Date;
}
Rooms:
#Entity({ name: 'rooms' })
export class Room {
#PrimaryGeneratedColumn()
id: number;
#Column({ default: '' })
name: string;
#Column({ nullable: true })
description: string;
#Column({ default: 'New' })
status: string;
#OneToOne(() => RoomServer, { nullable: false })
#JoinColumn()
roomServer: RoomServer;
}
When i type sql query
select * from "room-servers" rm left join rooms r on rm.id = r."roomServerId";
It returns results (3 servers that i have in database)
But when i try to use queryBuilder to see results:
const freeSocketServers = await this.roomServerRepository
.createQueryBuilder('room-servers')
.leftJoinAndSelect('room-servers.id', 'roomServerId')
.getMany();
console.log('freeSocketServer', freeSocketServers);
It returns nothing and i can't see console.log, it breaks on .leftJoinAndSelect
You set the relation in the room entity, To make it work you should go from room repository
const freeSocketServers = await this.roomRepository
.createQueryBuilder('room')
.leftJoinAndSelect('room.roomServer', 'room-server')
.getMany();
console.log('freeSocketServer', freeSocketServers);
Or you can make it Bi-directional see One-to-One