NestJS-Prisma How to create record with relational fields? - nestjs

i'm a begginer on NestJS and Prisma.
I'm trying to create an User, my table has relational Fields with table Addresses.
To create an user, i need first add a register into adresses table, to use adress_id on my user table.
I'm getting this error:
This is my code
Service:
async create(createUserDto: CreateUserDto) {
const hash = crypto.SHA256(createUserDto.password);
const passwordHash = (hash.toString(crypto.enc.Hex).toUpperCase());
const createCategory = await this.client.user.create({
data: {
name: createUserDto.name,
email: createUserDto.email,
age: createUserDto.age,
password: passwordHash,
roleId: createUserDto.roleId,
address: {
create: [
{
street: createUserDto.address.street,
number: createUserDto.address.number,
complement: createUserDto.address.complement,
neighborhood: createUserDto.address.neighborhood,
cityId: createUserDto.address.cityId,
stateId: createUserDto.address.stateId,
zipcode: createUserDto.address.zipcode
},
],
},
},
})
}
DTO:
export class CreateUserDto {
readonly id: number
readonly name :string
readonly age :any
readonly email :any
readonly password :any
readonly roleId :any
readonly addressId: number
readonly address: {
street: string,
number: number,
complement: string,
neighborhood: string,
cityId: number,
stateId: number,
zipcode: string
}
}
Schema.prisma
model user {
id Int #id #default(autoincrement())
name String
age Int
email String #unique
password String
roleId Int
role role #relation(fields: [roleId], references: [id])
addressId Int
address addresses #relation(fields: [addressId], references: [id])
}
model addresses {
id Int #id #default(autoincrement())
street String
number String
complement String
neighborhood String
cityId Int
city cities #relation(fields: [cityId], references: [id])
stateId Int
state state #relation(fields: [stateId], references: [id])
zipcode String
user user[]
}
What am i doing wrong?
Thanks!

Your address.create syntax is wrong. User-Address is a one-to-many relation, so one user can only have one address. So address.create should be passed a single address object, not an array.
This should work fine
const createCategory = await this.client.user.create({
data: {
name: createUserDto.name,
email: createUserDto.email,
age: createUserDto.age,
password: passwordHash,
roleId: createUserDto.roleId,
address: {
create: {
street: createUserDto.address.street,
number: createUserDto.address.number,
complement: createUserDto.address.complement,
neighborhood: createUserDto.address.neighborhood,
cityId: createUserDto.address.cityId,
stateId: createUserDto.address.stateId,
zipcode: createUserDto.address.zipcode
},
},
},
})

Related

Get custom attribute depend on pivot table in nest js with prisma ORM

What is the efficient way to map Prisma query results depending on the logged-on user and pivot table?
Here is my schema
model User {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
email String #unique
password String
firstName String
lastName String?
favouriteMovies FavouriteMovie[]
##map("users")
}
model Movie {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
title String
year Int
rating Float
category String
posterUrl String
favouriteMovies FavouriteMovie[]
##map("movies")
}
model FavouriteMovie {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
user User #relation(fields: [userId], references: [id], onDelete: Cascade)
userId Int
movie Movie #relation(fields: [movieId], references: [id], onDelete: Cascade)
movieId Int
##map("favourite_movies")
}
Which is the best way to retrieve isFavourite attribute with the Movie query result?
Here's the query which would return the movie details of the logged-in user.
import { PrismaClient } from '#prisma/client';
const prisma = new PrismaClient();
async function main() {
// Creating User
const user = await prisma.user.create({
data: {
email: 'sundarani#prisma.io',
firstName: 'Nurul',
lastName: 'Sundarani',
password: 'test',
},
});
// Creating Movie
const movie = await prisma.movie.create({
data: {
title: 'The Matrix',
category: 'Action',
posterUrl: 'https://i.imgur.com/dZQMx5q.jpg',
rating: 5,
year: 1999,
},
});
// Adding movie to user
const favouriteMovie = await prisma.favouriteMovie.create({
data: {
movieId: 1,
userId: 1,
},
});
// Getting Movie details of favourite movie of user
const getMovieDetailsFromUserId = await prisma.favouriteMovie.findMany({
where: {
userId: 1, // Logged In User
},
include: {
movie: true,
},
});
console.log(getMovieDetailsFromUserId);
}
main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});
Response:
[
{
id: 1,
createdAt: 2022-06-14T11:31:49.415Z,
updatedAt: 2022-06-14T11:31:49.417Z,
userId: 1,
movieId: 1,
movie: {
id: 1,
createdAt: 2022-06-14T11:30:10.747Z,
updatedAt: 2022-06-14T11:30:10.747Z,
title: 'The Matrix',
year: 1999,
rating: 5,
category: 'Action',
posterUrl: 'https://i.imgur.com/dZQMx5q.jpg'
}
}
]
Reference: Include.

AppSync + Serverless Error: Cannot return null for non-nullable type: 'null' within parent 'Query'

Here is my schema.graphql file
type User {
id: Int
email: String
}
type OrgUser {
id: Int
userId: Int
roleId: Int
orgId: Int
firstName: String
lastName: String
title: String
profileImage: String
user: User
}
type onSiteLead {
id: Int
userId: Int
roleId: Int
orgId: Int
firstName: String
lastName: String
title: String
profileImage: String
user: User,
lightColor: String
darkColor: String
}
type Job {
id: Int
name: String
jobDate: String
projectId: Int
resourceId: Int
userId: Int
project: Project
createdAt: String
}
type Customer {
id: Int
name: String
email: String
logo: String
phone: String
orgId: Int
}
type Project {
id: Int
name: String
customerId: String
onSiteLead: onSiteLead
customer: Customer
}
type Resource {
id: Int
name: String
startDate: String
endDate: String
userId: Int
categoryId: Int
lightColor: String
darkColor: String
user: OrgUser
jobs: [Job]
}
type SubCategories {
id: Int
name: String
startDate: String
endDate: String
parenCatId: Int
organizationId: Int
resources: [Resource]
}
type Category {
id: Int
name: String
startDate: String
endDate: String
parenCatId: Int
organizationId: Int
categories: [SubCategories]
resources: [Resource]
}
type SuperCategory {
id: Int
name: String
startDate: String
endDate: String
parenCatId: Int
organizationId: Int
categories: [Category]
resources: [Resource]
}
input jobInput {
id: Int
name: String
jobDate: String
projectId: Int
resourceId: Int
}
input listJobsInput {
startDate: String
endDate: String
superCat: [Int]
cat: [Int]
subCat: [Int]
}
input listCategoriesInput {
startDate: String
endDate: String
}
type listSuperCategories {
id: Int
name: String
startDate: String
endDate: String
parenCatId: Int
organizationId: Int
categories: [listCategories]
}
type listCategories {
id: Int
name: String
startDate: String
endDate: String
parenCatId: Int
organizationId: Int
categories: [listSubCategories]
}
type listSubCategories {
id: Int
name: String
startDate: String
endDate: String
parenCatId: Int
organizationId: Int
}
input jobData {
resourceId: Int!,
jobDate: String!
}
input pasteJobInput {
jobId: Int!
jobData: [jobData]!
}
type Query {
getJob(jobId: Int!): Job!
listJobs(data: listJobsInput): [SuperCategory]!
listCategories(data: listCategoriesInput): [listSuperCategories]!
}
type Mutation {
addJob(job: jobInput!): Job!
deleteJob(jobId: Int!): Int!
updateJob(job: jobInput!): Job!
pasteJob(data: pasteJobInput!): [Job]!
updateProjectLead(projectId: Int, userId: Int): Project!
}
type Subscription {
onAddJob: Job
#aws_subscribe(mutations: ["addJob"])
onDeleteJob: Int
#aws_subscribe(mutations: ["deleteJob"])
onUpdateJob: Job
#aws_subscribe(mutations: ["updateJob"])
onPasteJob: [Job]
#aws_subscribe(mutations: ["pasteJob"])
onUpdateProjectLead: Project
#aws_subscribe(mutations: ["updateProjectLead"])
}
schema {
query: Query
mutation: Mutation
subscription: Subscription
}
When i try to call any mutation or query(for example listCategories Query) after deployment to AWS, it's giving me error:
"message": "Cannot return null for non-nullable type: 'null' within parent 'Query'
It's Working fine when i try to call it locally. I am not sure where I am going wrong.
I have just had the same issue. My Lambda function handler needed an async
Functions must use the async keyword to use these methods to return a response or error.
https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html

can i use "AND" to where in connectOrCreate for prisma?

i want to make new holding. there are two cases.
there are no product, no account.
there are one product, account.
so i use connectOrCreate!. I want to find accountNum with userId and accountNumber
so i use AND in where. but there are error.
Unknown arg AND in data.accountNum.connectOrCreate.where.AND for type AccountNumberWhereUniqueInput. Did you mean id? Available args
const holding = await client.holding.create({
data: {
holdingNum,
accountNum: {
connectOrCreate: {
where: { AND: [{ userId: loggedInUser.id }, { accountNumber }] },
create: {
accountNumber,
user: {
connect: {
id: loggedInUser.id,
},
},
org: {
connect: {
orgCode,
},
},
},
},
},
product: {
connectOrCreate: {
where: {
prodCode,
},
create: {
prodCode,
prodName,
},
},
},
},
});
model AccountNumber {
id Int #id #default(autoincrement())
org Organization #relation(fields: [orgId], references: [id])
orgId Int
user User #relation(fields: [userId], references: [id])
userId Int
accountNum String
holdings Holding[]
}
model Holding {
id Int #id #default(autoincrement())
accountNum AccountNumber #relation(fields: [accountNumId], references: [id])
accountNumId Int
product Product #relation(fields: [productId], references: [id])
productId Int
holdingNum Int
evalAmt Int?
}
model Product {
id Int #id #default(autoincrement())
prodName String
prodCode String #unique
posts Post[]
holdings Holding[]
proposes Propose[]
}
I think you do not need the AND :
accountNum: {
connectOrCreate: {
where: { userId: loggedInUser.id , accountNumber },
...
}

Automatically add UUID relation on prisma create

I have a User, UserProfile and Post model in my Postgres database. The User and UserProfile depend on each other. I am trying to create a User that automatically creates a UserProfile with it, but I can't seem to find out how to automatically assume the User's ID for the UserProfile relation, I am using UUID for the User model.
Schema Models
model User {
id String #id #default(uuid())
createdAt DateTime #default(now())
username String #unique #db.VarChar(20)
emailEncrypted String #unique
emailIv String #unique
password String
isMod Boolean #default(false)
isAdmin Boolean #default(false)
emailConfirmed Boolean #default(false)
profile UserProfile?
}
model UserProfile {
user User #relation(fields: [id], references: [id])
id String #unique
posts Post[]
comments Comment[]
}
model Post {
id String #id #default(uuid())
createdAt DateTime #default(now())
title String #db.VarChar(300)
caption String #db.VarChar(1000)
upvotes Int #default(0)
downvotes Int #default(0)
comments Comment[]
author UserProfile #relation(fields: [authorId], references: [id])
authorId String
}
Query
const user = await prisma.user.create({
data: {
username,
emailEncrypted: encrypted,
emailIv: iv,
password: hashedPassword,
profile: {
create: {}, // create a UserProfile that assumes the created user's UUID as a relation
},
},
select: {
id: true,
},
});
As you can see, I have tried to use create: {} in order to assume the user's UUID, but it fails to create an actual UserProfile, just a User, which of course breaks the system.
I ran this as well. In order to include profile data after creating the user I did the following tweak.
const user = await prisma.user.create({
data: {
username: "username",
emailEncrypted: "encrypted",
emailIv: "iv",
password: "hashedPassword",
profile: {
create: {},
},
},
select: {
id: true,
createdAt: true,
emailConfirmed: true,
emailIv: true,
emailEncrypted: true,
isAdmin: true,
isMod: true,
password: true,
profile: true,
username: true,
},
});
This outputs,
No issue it worked fine.
Still wondering what the issue you faced was.
Can you paste the error log ?.
This is the correct way of adding relations in Prisma. You use create to add a relation and the UUID will automatically be added to that record. You do not need to do anything else. I tried the following and works fine for me:

How to connect multiple m-n relationship records

I have a schema that looks like this:
model School {
id Int #id #default(autoincrement())
name String
teachers Teacher[]
students Student[]
}
model Teacher {
id Int #id #default(autoincrement())
firstName String
lastName String
schools School[]
students Student[]
}
model Student {
id Int #id #default(autoincrement())
firstName String
lastName String
teacherId Int
teacher Teacher #relation(fields: [teacherId], references: [id])
schoolId Int
school School #relation(fields: [schoolId], references: [id])
}
I want to create in a single call a school, with teacher and student. This is my attempt:
prisma.school.create({
data: {
name: "Best",
teachers: {
create: {
id: 2,
firstName: "Charles",
lastName: "Wise",
students: {
create: {
firstName: "Pauline",
lastName: "Jenkins",
school: {
connect: {
id: -1 // How to reference a school that is being created?
}
}
}
}
}
}
}
});
Unfortunately I have no clue how to pass a school's id when creating a student.
I know that I can do it in two calls by first creating a school with a teacher and then creating a student with that just created school and teacher:
const school = await prisma.school.create({
data: {
name: "Best",
teachers: {
create: {
id: 2,
firstName: "Charles",
lastName: "Wise",
}
}
},
include: {
teachers: true,
}
});
await prisma.student.create({
data: {
firstName: "Pauline",
lastName: "Jenkins",
school: {
connect: {
id: school.id
}
},
teacher: {
connect: {
id: school.teachers[0].id
}
}
}
});
But that looks kind of weird and error prone.
Is there a way to rewrite it to a single call?
You can try this code snippet to either connect to if a record exists or create on the go when it is not there.
prisma.teachers.create({
data: {
id: 2,
firstName: 'Charles',
lastName: 'Wise',
students: {
create: {
firstName: 'Pauline',
lastName: 'Jenkins',
},
},
school: {
connectOrCreate: {
where: {
name: 'best',
},
create: {
name: 'best',
},
},
},
},
});

Resources