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',
},
},
},
},
});
Related
I have this model for a user, the user can also be a driver and the driver have an array of cars. I want to delete a specific car from all the cars of drivers, but my query deletes all the cars.
This is the schema:
const UserSchema = new mongoose.Schema({
name: {
type: String,
},
driverData: {
ExperienceLevel: {
type: String,
},
rides: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "ride.model",
},
],
cars: [
{
id: {
type: mongoose.Schema.Types.ObjectId,
},
licensePlateNumber: {
type: String,
},
},
],
},
});
Code I am using to pull a car by id.
user = await User.findByIdAndUpdate(
{ _id: userId },
{ driverData: { cars: { $pull: { id: carId } } } }
);
Only a single car object and a single car id is left after making this query, all other data is removed. How to only remove only a single car.
Your syntax is incorrect. Try this:
user = await User.findByIdAndUpdate( { _id: userId }, { $pull: { driverData: { cars: { $elemMatch: { id: carId } } } } );
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.
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
},
},
},
})
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 },
...
}
This is my schema, and in MongoDB I have separate collections for users, events and movies due to the large number of events and movies:
type Event {
id: ID!
title: String!
description: String!
creator: User!
}
type Movie {
id: ID!
title: String!
releaseDate: String
}
type MovieStatus {
movie: Movie
status: StatusEnum // WATCHED, PLANNING_TO_WATCH
}
type User {
id: ID!
firstName: String!
createdEvents: [Event!]
movies: [MovieStatus!]
}
And I want to create the following query:
query {
user(id: "12345") {
id
firstName
createdEvents{
id
title
description
}
movies{
movie {
id
title
releaseDate
}
status
}
}
}
I have no problem getting the events, by including this in my resolvers:
User: {
createdEvents: ({ createdEvents }) =>
Event.find({ _id: { $in: createdEvents } }),
},
But I can't figure out how to access the movie id, title and release dates.
movies: ({ movies }) => {
return Promise.all(
movies.map(async (m) => {
const movie = m
movie.movie = await Movie.findById(movie.movie)
return movie
})
)
}