I have a Call entity that contains a user with a ManyToOne relation (and some other irrelevant fields).
So, the entity looks like that:
#Entity()
export class Call extends BaseEntity {
#ManyToOne(() => User, {cascade: true, eager: true})
user: User;
}
I want to update that Call so it will be connected to userId 1 (for example).
When I am trying to update the call with other userID - I am getting a TypeError:
Call.update({ id: 1 }, { user: 2 })
(Because type number is not from type User)
What is the best way of doing that (without using "any")?
Should be
Call.update(1, { user: { id: 2, ...other props } })
Related
I have this model:
#Entity()
export class Trade extends BaseEntity {
...
#OneToOne(() => Fee, { cascade: true })
#JoinColumn()
fee: Fee;
...
}
#Entity()
export class Fee extends BaseEntity {
...
#OneToOne(() => Trade, trade => trade.fee)
trade!: Trade
...
}
I'm trying to get the equivalent of:
await getManager().find(Trade, { relations: ['fee'] })
with the QueryBuilder.
await createQueryBuilder('trade')
.leftJoinAndSelect(Fee, 'fee', 'fee.tradeId = trade.feeTradeId')
.getMany()
await getManager().find(Trade, { relations: ['fee'] })
My problem: when I use getManager().find(...) the fee property gets populated with the relation, however, when using the QueryBuilder it is not (trade.fee is undefined).
How can I get fee populated using a left join with the query builder?
The syntax is incorrect:
await createQueryBuilder('trade')
.leftJoinAndSelect('trade.fee', 'fee', 'fee.tradeId = trade.feeTradeId')
.getMany()
you may get the data without mentioning the condition
await createQueryBuilder('trade')
.leftJoinAndSelect('trade.fee', 'fee')
.getMany()
here's a question explaining the syntax: Explain typeorm join syntax
I have a user table, and one of the columns is contacts which references itself. Now I am trying to get all the user’s contacts. However it is not returning the references. I am not exactly sure are to where the problem can be. Lets say I have a user table that looks like this
id | name | email | contacts_Id
---|---------|---------------------------|-----
1 | foo | foo#foo.com | 2
2 | bar | bar#bar.com | 1
3 | baz | baz#baz.com | 1 2
The entity is like this:
export class User {
#PrimaryGeneratedColumn()
public id: number;
#Column()
public email: string;
#ManyToOne(type => User, user => user.contacts, {
cascade: true,
})
public contact: User;
#OneToMany(type => User, user => user.contact)
public contacts: User[];
}
and I am querying like this:
const userRepo = getManager().getRepository('users');
const data = (await userRepo.findOne({ where: { email: email }, relations: ['contacts'] })) as UserData;
with the code above I get the user data (id, name, email) the contacts section is empty []
solved:
change:
const data = (await userRepo.findOne({ where: { email: email }, relations: ['contacts'] })) as UserData;
to
const data = (await userRepo.findOne({ where: { email: email }, relations: ['contacts'] })) as User;
since we are referencing the entity
I literally did the same thing (copied your entity), difference being that I injected repository into my service, I'm using mySQL, and I guess you're using PostgreSQL but it works for me.
The thing that is bugging me is your column contacts_Id, by default typeorm will generate a camel case foreign key column (contactId) unless specified differently by JoinColumn() decorator, so maybe that's what causing the issues.
(I wanted to comment but don't have enough rep to post a comment.)
I'm setting up a server using TypeORM + PostgreSQL. When saving saving my entity to the entity's repository, I receive the error: TypeError: relatedEntities.forEach is not a function and the entity is not saved to the database.
This seems to only happen when I am using the #OneToMany or #TreeChildren decorators.
Here is my entity class that is causing the problem:
import { ServiceData } from './service-data.entity';
import { ManufacturerData } from './manufacturer-data.entity';
import { Entity, Column, PrimaryGeneratedColumn, TreeChildren } from 'typeorm';
#Entity()
export class Advertisement {
#PrimaryGeneratedColumn()
id: number;
#Column({ nullable: true })
name?: string;
#Column()
gatewayId: string;
#Column()
rssi: number;
#Column({ nullable: true })
mac?: string;
#TreeChildren()
manufacturerData?: ManufacturerData[];
#TreeChildren()
serviceData?: ServiceData;
}
The (abbreviated) error output is:
UnhandledPromiseRejectionWarning: TypeError: relatedEntities.forEach is not a function
at OneToManySubjectBuilder.buildForSubjectRelation (/<project-directory>/src/persistence/subject-builder/OneToManySubjectBuilder.ts:78:25)
Found the problem.
#TreeChildren and #OneToMany always expect an array. I had to change serviceData?: ServiceData; to serviceData?: ServiceData[];
This error can come up when the oneTomany relationships are not properly written in the Entity design and also when you trying to store the relationships in a table.
The first One is, setting the Entity holding many of the other Entity like this
#OneToMany(() => Address, (address) => address.users)
address: Address[];
The other entity that has manyToOne relationship like this,
#ManyToOne(() => Users, (users) => users.address)
users: Users;
If the relationships are all good, then the problem is storing the entity relations to the database.
when creating the user, store the relationships like this
address = await this.addressRepository.findOneOrFail({
where: {
user_id: Number(userId),
},
});
const user = new User();
user.name = name;
user.age = age;
### store the address as an array of objects to the relationship column
users.address = [address]
I have an Entity Transaction and an Entity Integration
#Entity()
export default class Transaction {
#PrimaryGeneratedColumn()
public id_trans?: number;
#OneToOne(type => Integration, i => i.transaction, { nullable: true })
public integration?: Integration;
}
and
#Entity()
export default class Integration {
#PrimaryGeneratedColumn()
public id_cust?: number;
#OneToOne(type => Transaction, t => t.integration)
#JoinColumn({ referencedColumnName: 'id_trans', name: 'int_id_module' })
public transaction?: Transaction;
}
I tried to query the Transaction by using a Integration property as filter.
const id_api = 10;
const transaction = await repository.find({
where: { integration: { int_id_api: id_api} },
relations: ['integration', 'customer'],
});
but it returns the entire table of Transactions, even if the integration.int_id_api is different from id_api property
What am I doing wrong. What should I do to get this query working ?
You need to add a primary key to all your entities. From the doc:
Each entity must have at least one primary key column. This is a
requirement and you can't avoid it. To make a column a primary key,
you need to use #PrimaryColumn decorator.
Assuming you update the Integration entity like so
#Entity()
export default class Integration {
#PrimaryColumn()
public id_inte: number;
#OneToOne(type => Transaction, t => t.integration)
#JoinColumn({ referencedColumnName: 'id_trans', name: 'int_id_module' })
public transaction?: Transaction;
}
You should be able to find transactions like so
const transaction = await repository.find({
where: { integration: { id_inte: some_id } },
relations: ['integration', 'customer'],
});
Is their any possibility to use mongoDB ObjectID system with MySql and typeORM instead of using an incremental ID?
The goal would be to define my entity like this:
#Entity()
export class RolePermission implements IRolePermission {
#ObjectIdColumn() id?: ObjectID;
#Column()
#IsNotEmpty()
roleId: ObjectID;
#Column()
#IsNotEmpty()
permissionId: ObjectID;
}
My entities could therefore have an ID without even being persisted. The ObjectId system would prevent collisions on the unique constraint I'd like to use for this column.
If a system like that can be implemented, is their any performance downside? I remember implementing such a system with PHP, and at the time, I had read this response that made me think that it was ok: Is there a REAL performance difference between INT and VARCHAR primary keys?
It's in fact really simple. You just need to use the ObjectID object from the mongodb package and declare your entities like you would do usually.
First, install mongodb dependencies:
yarn add mongodb
yarn add #types/mongodb
Then, declare your entity. Here an example with a working relationship between a user and an article:
user.entity.ts:
import { Entity, Column, ManyToOne, PrimaryColumn } from 'typeorm';
import { Article } from './article.entity';
import { ObjectID } from 'mongodb';
#Entity()
export class User {
constructor() {
this.id = (new ObjectID()).toString();
}
#PrimaryColumn()
id: string;
#Column({ length: 500 })
username: string = null;
#OneToMany(type => Article, article => article.user)
articles: Article[];
}
article.entity.ts:
import { Entity, Column, ManyToOne, PrimaryColumn } from 'typeorm';
import { User } from './user.entity';
import { ObjectID } from 'mongodb';
#Entity()
export class Article {
constructor() {
this.id = (new ObjectID()).toString();
}
#PrimaryColumn()
id: string;
#Column({ length: 500 })
title: string = null;
#ManyToOne(type => User, user => user.articles, {nullable: true})
user: User;
}
And use it as you would normally do:
const user = new User();
user.username = 'email#adress.com';
const article = new Article();
article.title = 'Mon titre';
article.user = user;
await this.userRepository.save(user);
await this.articleRepository.save(article);