TypeORM throws an error after insert with the queryBuilder in Nest.js - express

I have an entity and service defined as follows.
user.entity.js
#Entity({ name: 'users' })
export class User {
#Column({
type: 'binary',
length: 16,
select: false,
primary: true,
default: () => `(UUID_TO_BIN(UUID(), 1))`,
})
id: string;
#Index()
#Column({ type: 'varchar', length: 225, nullable: false })
name: string;
#Column({ type: 'varchar', length: 15, unique: true, nullable: false })
MSISDN: string;
#Column({ type: 'varchar', length: 225, unique: true, nullable: false })
email_address: string;
#Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
created_at: Date;
#Column({ type: 'datetime', nullable: true, onUpdate: 'CURRENT_TIMESTAMP' })
updated_at: Date;
}
user.service.js
#Injectable()
export class UserService {
constructor(
#InjectRepository(User)
private usersRepository: Repository<User>,
) {}
create(user: DeepPartial<User>): Promise<User> {
return this.usersRepository
.createQueryBuilder()
.insert()
.values({ ...user})
.execute();
}
}
Whenever I attempt to create a user from the Postman client, the record is in fact inserted into the database but I get a 500 response from the postman client.
Postman response
{
"statusCode": 500,
"message": "Internal server error"
}
The CLI error looks like this:
[Nest] 9084 - 15/03/2021, 11:17:47 [ExceptionsHandler] Cannot update entity because entity id is not set in the entity. +331142ms
Error: Cannot update entity because entity id is not set in the entity.
at C:\Users\Mnengwa\workspace\kodisha\kodisha-web-api\node_modules\typeorm\query-builder\ReturningResultsEntityUpdator.js:128:39
at Array.map (<anonymous>)
at ReturningResultsEntityUpdator.<anonymous> (C:\Users\Mnengwa\workspace\kodisha\kodisha-web-api\node_modules\typeorm\query-builder\ReturningResultsEntityUpdator.js:122:46)
at step (C:\Users\Mnengwa\workspace\kodisha\kodisha-web-api\node_modules\typeorm\node_modules\tslib\tslib.js:141:27)
at Object.next (C:\Users\Mnengwa\workspace\kodisha\kodisha-web-api\node_modules\typeorm\node_modules\tslib\tslib.js:122:57)
at C:\Users\Mnengwa\workspace\kodisha\kodisha-web-api\node_modules\typeorm\node_modules\tslib\tslib.js:115:75
at new Promise (<anonymous>)
at Object.__awaiter (C:\Users\Mnengwa\workspace\kodisha\kodisha-web-api\node_modules\typeorm\node_modules\tslib\tslib.js:111:16)
at ReturningResultsEntityUpdator.insert (C:\Users\Mnengwa\workspace\kodisha\kodisha-web-api\node_modules\typeorm\query-builder\ReturningResultsEntityUpdator.js:87:24)
at InsertQueryBuilder.<anonymous> (C:\Users\Mnengwa\workspace\kodisha\kodisha-web-api\node_modules\typeorm\query-builder\InsertQueryBuilder.js:105:76)

I had to specify the reload option as false in my save call (not insert) to make the error go away.
For insert you want to add an updateEntity(false) call to your chain before calling execute.
There's more context here:
https://github.com/typeorm/typeorm/issues/4651

Try defining the id attribute for the User entity as follows -
#PrimaryColumn()
#Generated('uuid')
id: string;

Related

EntityColumnNotFound: No entity column "authors" was found. many to many relations on TypeORM and NestJS

I am trying to get the books per user from the get request
I have the following problem, it turns out that I am doing a many-to-many relationship but it indicates that the authors entity was not found, I have already searched the TypeORM documentation but I cannot find anything, this is my code:
book.controller.ts
#Controller('book')
export class BookController {
constructor(
private readonly _bookService: BookService
) { }
#Get('author/:authorId')
getBooksByAuthor(
#Param('authorId', ParseIntPipe) authorId: number,
): Promise<ReadBookDto[]> {
return this._bookService.getBooksByAuthor(authorId);
}
}
book.service.ts
#Injectable()
export class BookService {
constructor(
#InjectRepository(BookRepository)
private readonly _bookRepository: BookRepository,
#InjectRepository(UserRepository)
private readonly _userRepository: UserRepository
) { }
async getBooksByAuthor(authorId: number): Promise<ReadBookDto[]> {
const books: Book[] = await this._bookRepository.find({
// This is where I have the entity of authors, it should be noted that the entity of books if I have it
where: { status: status.ACTIVE, authors: In([authorId]) },
})
console.log(books)
return books.map(book => plainToClass(ReadBookDto, book));
}
}
book.entity.ts
import {
BaseEntity,
PrimaryGeneratedColumn,
Column,
ManyToMany,
Entity,
JoinColumn,
CreateDateColumn,
UpdateDateColumn,
} from 'typeorm';
import { User } from '../user/user.entity';
#Entity('books')
export class Book extends BaseEntity {
#PrimaryGeneratedColumn('increment')
id: number;
#Column({ type: 'varchar', length: 100, nullable: false })
name: string;
#Column({ type: 'varchar', length: 500 })
description: string;
#ManyToMany(type => User, user => user.books, { eager: true, primary: true})
#JoinColumn()
authors: User[];
#Column({ type: 'varchar', default: 'ACTIVE', length: 8 })
status: string;
#CreateDateColumn({ type: 'timestamp', name: 'created_at' })
createdAt: Date;
#UpdateDateColumn({ type: 'timestamp', name: 'updated_at' })
updatedAt: Date;
}
This is the user entity where I make the many to many relation
user.entity.ts
#Entity('users')
export class User extends BaseEntity {
#PrimaryGeneratedColumn('increment')
id: number;
#Column({ type: 'varchar', unique: true, length: 25, nullable: false })
username: string;
#Column({ type: 'varchar', nullable: false })
email: string;
#Column({ type: 'varchar', nullable: false })
password: string;
#OneToOne(type => UserDetails, {
cascade: true,
nullable: false,
eager: true,
})
#JoinColumn({ name: 'detail_id' })
details: UserDetails;
#ManyToMany(type => Book, book => book.authors)
#JoinTable({ name: 'user_books' })
books: Book[];
}
If you could help me find the error it would be very helpful
Thanks
You can use queryBuilder to get the books:
#Injectable()
export class BookService {
constructor(
#InjectRepository(BookRepository)
private readonly _bookRepository: BookRepository,
#InjectRepository(UserRepository)
private readonly _userRepository: UserRepository
) { }
async getBooksByAuthor(authorId: number): Promise<ReadBookDto[]> {
const books: Book[] = await this._bookRepository.createQueryBuilder('books')
.leftJoinAndSelect("books.authors", "users")
.where('books.status = :status',{status : status.ACTIVE})
.andWhere("users.id = :id ", { id: authorId })
.getMany();
console.log(books)
return books.map(book => plainToClass(ReadBookDto, book));
}
}

typeorm composition with type-graphql : need mixins?

I'm trying to use TypeOrm composition together with type-graphql, but I can not find a way to declare the object types.
The goal is to have a final entity NewBudgetEntity composed with 3 entities : MyBaseEntity, BudgetHeaderEntity and BudgetHeaderEntity
I have run the code below and it works fine, but the graphql schema is not reflecting the table.
In the table, as expected, there are all the columns of the 3 entities.
But in type-graphql, because I've add the #ObjectType in the main entity, the fields header and corps are in the Graphql schema, whereas they are not in the table.
I think I need to use mixins to make sure that the final #ObjectType extends the 3 other #ObjectTypes related to the 3 other entities, but I'm quite confused how to do it. I read the doc of type-graphql about mixins, but can not get it work on my project.
Here is the code that is running well, but I don't want 'header' and 'corps' to be part of the graphql query
Ths for your help
import { Field, Float, ID, InputType, ObjectType } from "type-graphql";
import { BaseEntity, Column, Generated, Index, PrimaryColumn } from "typeorm";
export interface IIdentifier {
id: string;
}
export interface IBudgetHeader {
codeBudget: string;
natureBudget: string;
}
export interface IBudgetCorps {
montant: number;
nom: string;
isAffectable: boolean;
}
#ObjectType()
#InputType("myBaseEntityInputType")
export class MyBaseEntity extends BaseEntity implements IIdentifier {
#Field(() => ID, { nullable: false })
#PrimaryColumn({ type: "uuid" })
#Index()
#Generated("uuid")
id: string;
}
#ObjectType()
#InputType("BudgetHeaderEntityInputType")
export class BudgetHeaderEntity implements IBudgetHeader {
#Field({ nullable: false })
#Column({
type: "character varying",
length: 20,
nullable: false,
unique: true,
default: "",
})
codeBudget: string;
#Field({ nullable: true })
#Column({
type: "character varying",
length: 20,
nullable: true,
default: "",
})
natureBudget: string;
}
#ObjectType()
#InputType("BudgetCorpsEntityInputType")
export class BudgetCorpsEntity implements Partial<IBudgetCorps> {
#Field({ nullable: true })
#Column({
type: "character varying",
length: 250,
nullable: true,
default: "",
})
nom: string;
#Field(() => Boolean, { nullable: true })
#Column({
type: "bool",
default: false,
nullable: true,
})
isAffectable: boolean;
#Field(() => Float, { nullable: true })
#Column({
type: "float",
default: 0.0,
nullable: true,
})
montant: number;
}
#ObjectType()
#InputType("NewBudgetEntityInputType")
#Entity({
name: "newbudget",
})
export class NewBudgetEntity extends MyBaseEntity {
#Field(() => BudgetHeaderEntity)
header: BudgetHeaderEntity;
#Field(() => BudgetCorpsEntity)
corps: BudgetCorpsEntity;
}
#Resolver(NewBudgetEntity)
export default class NewBudgetEntityResolvers extends apiNewBudgetEntity {
#Query()
dummy(): string {
console.log("test");
return "test";
}
}
Example of query but I want to avoid 'header{} and corps{} and just having data {id codeBudget nom}
If you want to hide some property from being exposed in GraphQL schema, just don't put #Field decorator above the property. If the property should be mapped to db column, just use #Column decorator only.

TypeORM getRepository.find() does not include Foreign Key Fields

I am trying to fetch all the columns included on my entity, but I only able to fetch the columns that does not have any relationship from the other entity.
I use this block of codes to fetch the all the rows to this repository.
private translationTextRepository = getRepository(TranslationText);
async all(request: Request, response: Response, next: NextFunction) {
return this.translationTextRepository.find();
}
And here's the entity for this repository.
#Entity('TranslationText')
export class TranslationText {
#PrimaryGeneratedColumn()
ID: number;
#Column()
CreatedBy: string;
#Column({ type: 'timestamp', default: () => 'CURRENT_TIMESTAMP' })
CreatedDate: Date;
#Column()
Status: boolean;
#Column({ nullable: true, default: null })
ModifiedBy: string;
#Column({ type: 'timestamp', nullable: true, default: null })
ModifiedDate: Date;
#Column()
Text: string;
#ManyToOne((type) => Locale, (locale) => locale.ID)
#JoinColumn({ name: 'LocaleID' })
LocaleID: Locale;
#ManyToOne((type) => TranslationTitle, (translationTitle) => translationTitle.ID)
#JoinColumn({ name: 'TranslationTitleID' })
TranslationTitleID: TranslationTitle;
}
But I was only able to fetch all the columns except the LocaleID and the TranslationTitleID.
How can I achieve this?
Check this document:
https://typeorm.io/#/relations-faq/how-to-use-relation-id-without-joining-relation
solution:
define new column:
#column()
LocaleID: number
rename old one to : Locale
But typeOrm cannot sync your table due to foreign key problem.
use eager option in #ManyToOne({eager: true})
The search result will contain relation Locale object, you can take id from it.
Can you try to specify the relations like that:
async all(request: Request, response: Response, next: NextFunction) {
return this.translationTextRepository.find({
relations:["LocaleID","TranslationTitleID"]
});
}
Because you have to make explicit that you want your relations on the query.

Realm does not seems to working

I am trying to use realm in react-native android and I just wanted to test if it is working or not.
It seems to save data since it throws duplicated primaryKey error.
However, realm.objects('Person') does not return data but
Proxy
[[Handler]]
:
Object
[[Target]]
:
Results
[[IsRevoked]]
:
false
class Person {}
Person.schema = {
name: 'Person',
primaryKey: 'name',
properties: {
name: 'string',
age: {type: 'int', default: 0},
},
};
const realm = new Realm({schema: [Person],schemaVersion: 2});
// Write
realm.write(() => {
const savedPerson = realm.create('Person', {
name: 'Hal Incanden1za',
age: 17,
});
});
console.log(realm.objects('Person'))
The value you get from a realm.objects() call is not a normal array, so console.log may not be doing what you are expecting here. Try iterating through it instead.

Unique Array objects in mongoose schema

I have a conversation schema which will allow users for private messaging, each two users can be in ONE conversation therefore, the recipients in the conversations should be unique
/** Users in this conversation**/
var usersSchema = new Schema({
id: {
type: Schema.Types.ObjectId,
index: true,
required: true,
ref: 'User'
},
name: {
type: String,
required: true
}
});
/** For each message we will have the below **/
var messagesSchema = new Schema({
from: {
type: Schema.Types.ObjectId,
required: true
},
content: {
type: String,
required: true
},
read: {
type: Boolean,
default: false
}
}, {
timestamps: true
});
/** Now all together inside the thread schema **/
var conversationsSchema = new Schema({
users: {
type: [usersSchema],
required: true,
index: true,
unique: true
},
messages: [messagesSchema],
}, {
timestamps: true
});
var Conversation = mongoose.model('Conversation', conversationsSchema);
module.exports.Conversation = Conversation;
The only way I can think of is to manually check by looking into the IDs inside the users array in the conversation schema. However, I think there is a way in mongoose to do that.
You can add unique : true in your userSchema to only allow unique users in a conversation.
/** Users in this conversation**/
var usersSchema = new Schema({
id: {
type: Schema.Types.ObjectId,
index: true,
required: true,
unique : true, //add unique behaviour here
ref: 'User'
},
name: {
type: String,
required: true
}
});