Typeorm, MongoDB and TypeGraphQL - Populate - Lookup - mongodb

I am working with Typeorm and MongoDB. I have a UserAlert entity that saves the _id of another User entity as a field. My question is how you can get the information of the entity that that _id refers to. It would be something similar to populate in mongoose.
Example:
User:
#Entity({ name: 'Users' })
export default class User extends BaseEntity {
#ObjectIdColumn()
_id!: ObjectID;
#Column('string')
firstName!: string;
#Column('string')
lastName!: string;
#Column('string')
phoneNumber!: string;
}
User Alert:
#Entity({ name: 'UserAlerts' })
export default class UserAlert extends BaseEntity {
#ObjectIdColumn()
_id!: ObjectID;
//REFERENCE
#ObjectIdColumn()
userId!: ObjectID;
#Column('date')
date!: Date;
}
Result: User Alert
{
"_id":"asdbfsdf32112312dasdas",
"date":"15/09/2021",
"User":{
"_id":"asdas6d5412634123654",
"firstName":"Jorge",
"lastName":"Mamani",
"phoneNumber":"465465"
}
}
How would I have to present the data in Type GraphQL?

Related

Prisma constraint not available

I`m using Prisma with NestJS and PostgreSQL
In my schema.prisma i have this
model User {
userId Int #id #default(autoincrement())
firstName String? #db.VarChar(25)
lastName String? #db.VarChar(25)
login String #unique #db.VarChar(60)
email String #unique
password String
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
role Role? #default(ADMIN)
createdUsers User[] #relation("createdBy")
createdBy User? #relation("createdBy", fields: [creatorId], references: [userId])
creatorId Int?
}
enum Role {
ADMIN
MANAGER
WAREHOUSE
USER
}
So when a make create request like this
{
login: "A",
email: "A",
password: "A"
}
it saves in DB - that`s ok. By after the same request i get this error "Unique constraint failed on the (not available)". So shouldn't there be a not unique column name instead of (not available) or that is ok case? Where am i wrong?
I was trying drop table Users and make different unique combs, don`t know what else i can do...
UPD:
async create(createUserDto: CreateUserDto) {
return this.prisma.user.create({
data: {
...createUserDto
}
})
}
export class CreateUserDto {
#IsNotEmpty()
login: string;
#IsNotEmpty()
#IsEmail()
email: string;
#IsNotEmpty()
#MinLength(6)
password: string;
}
UPD 2.0
Finally, moved to TypeORM, it is bug like #num8er mentioned
https://github.com/prisma/prisma/issues/10829
Ty for all the replies

How to create nested DTO class in NestJS corresponding to Schema

I am new to NestJs and trying to create nested schema in Mongoose as I want this data structure in my database:
{
name:"John",
age:28,
address:{
city:"Delhi",
state:"Delhi
}
}
For this I have created below mongoose schema:
user.schema.ts
import mongoose from "mongoose";
export const UserSchema = new mongoose.Schema({
name:{type:String},
age:{type:Number},
address:{
city:{type:String},
state:{type:String}
}
});
How Can I write Dto class for this schema.Someone let me know As I want to add data inside database.
You can simply create two DTO classes in the following way.
export class AdressDto {
readonly city: string;
readonly state: string;
}
export class UserDto {
readonly name: string;
readonly age: number;
readonly address: AdressDto
}
In the official Nestjs documentation you can find how to use DTO
in your controllers, and you can also find how to use validators if you want to use them.

have RelationID on both sides of OneToOne relation typeorm postgres

I have user and profile entities and they have a onetoone relation together.
I am using typeorm and postgres
I used joincolumn on user and have access to RelationId (or Column) profileId on user side
However I want to have userId on profile side as well
How can I accomplish this?
something like this:
export class User extends BaseEntity {
#OneToOne(()=>Profile)
profile:number
#Column()
profileId:number
}
////////
export class Profile extends BaseEntity{
#OneToOne(()=>Profile)
user: number
#Column()
userId: number
}
You may find answer in documantation.
Relations can be uni-directional and bi-directional. Uni-directional are relations with a relation decorator only on one side. Bi-directional are relations with decorators on both sides of a relation.
#JoinColumn must only be on one side of the relation - on the table that will own the foreign key.
import {User} from "./User";
#Entity()
export class Profile {
#PrimaryGeneratedColumn()
id: number;
#Column()
gender: string;
#Column()
photo: string;
#OneToOne(type => User, user => user.profile) // specify inverse side as a second parameter
user: User;
}
import {Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn} from "typeorm";
import {Profile} from "./Profile";
#Entity()
export class User {
#PrimaryGeneratedColumn()
id: number;
#Column()
name: string;
#OneToOne(type => Profile, profile => profile.user) // specify inverse side as a second parameter
#JoinColumn()
profile: Profile;
}

QueryFailedError: insert or update on table "graph" violates foreign key constraint "FK_0e40......"

I created a very small reproduction repository.
Please also have a look at my possible fix down below.
I have a graph and a graph node entity. The graph only knows about its start graph node and the node itself knows about which graph it belongs to and its successor.
#Entity()
export class Graph extends BaseEntity {
#PrimaryGeneratedColumn("uuid")
public id: string;
#Column({ nullable: true })
public startNodeId?: string;
#ManyToOne(() => GraphNode)
#JoinColumn({ name: "startNodeId" })
public startNode?: GraphNode;
}
#Entity()
export class GraphNode extends BaseEntity {
#PrimaryGeneratedColumn("uuid")
public id: string;
#PrimaryColumn("uuid")
public graphId: string;
#ManyToOne(() => Graph, { onDelete: "CASCADE" })
#JoinColumn({ name: "graphId" })
public graph: Graph;
#Column({ nullable: true })
public successorGraphNodeId?: string;
#ManyToOne(() => GraphNode)
#JoinColumn({ name: "successorGraphNodeId" })
public successorGraphNode?: GraphNode;
}
As you can see the graph's startnode might be null. Further the graph node might have no successor, so this field might be null too. It's important that a graph node has a composite primary key, because it always belongs to one graph.
I created some very basic CRUD repository actions to create a graph and a graph node. Later on I want to update the start node id of that graph.
The graph nodes repository just creates a new entity
public createGraphNode(graphId: string, successorGraphNodeId?: string): Promise<GraphNode> {
const graphNode: GraphNode = new GraphNode();
graphNode.graphId = graphId;
graphNode.successorGraphNodeId = successorGraphNodeId;
return graphNode.save();
}
The graphs repository creates a new entity and is able to update its start node id
public createGraph(startNodeId?: string): Promise<Graph> {
const graph: Graph = new Graph();
graph.startNodeId = startNodeId;
return graph.save();
}
public updateStartNodeId(graphId: string, startNodeId: string): Promise<UpdateResult> {
return this.update(graphId, {
startNodeId
});
}
When running the application I create a new graph. After that I create a new graph node and assign the graph id to it. This graph node has no successor. Last I assign the graph node as the graph start node.
const graph: Graph = await graphsRepository.createGraph();
const graphNode: GraphNode = await graphNodesRepository.createGraphNode(graph.id);
await graphsRepository.updateStartNodeId(graph.id, graphNode.id);
By doing so I'm getting the following database error
QueryFailedError: insert or update on table "graph" violates foreign
key constraint "FK_0e4022833a9efc062c01637e552"
It seems my entity design is wrong. Does someone know how to fix it?
Thanks in advance
I might have a fix for it
Graph entity
Create a reference to the PK via referencedColumnName: "id"
#ManyToOne(() => GraphNode)
#JoinColumn({ name: "startNodeId", referencedColumnName: "id" })
public startNode?: GraphNode;
Graph node entity
Do the same for the successor graph node
#ManyToOne(() => GraphNode)
#JoinColumn({ name: "successorGraphNodeId", referencedColumnName: "id" })
public successorGraphNode?: GraphNode;
Also add the Unique decorator to the entity and mark the id field as unique
#Unique(["id"])
The only problem I have is that I don't know why I have to solve it this way.
I don't know why I have to reference the PK of the referenced table via referencedColumnName: "id", this should be obvious
I also don't know why I have to mark the id column as unique via #Unique(["id"]) because this field will always be unique
In your .Save() pass the id as parameter otherwise it will consider you are creating new data.

TS interface or class

Might be a silly question, but I just had a debate with a colleague.
What should be used in TS shape an object, a class or an interface?
I need to know that a function returns an object of a certain type, what should be used?
export class Person{
name: string;
lastName: strig;
dob: Date;
constructor() {}
}
or
export interface IPerson{
name: string;
lastName: string;
dob: Date;
}
For me the best way to create an Object is to use INTERFACE ! Because you can easily store it as an JSON Object on a database like Firebase... You have no function only properties
Then you could use the CLASS with functions to manage Objects type INTERFACE
The interface
export interface IObject {
id : string,
name: string,
description : string
}
And then the class
import { IObject } from "../interfaces/iobject";
export class ObjectService {
myObject = {} as IObject
constructor() {}
getDescription(anObject : IObject){ return anObject.description }
}