I´m doing an Spotify clone and I´m trying to add a song to a playlist but my query doesn't work, until this point, everything was good following the documentation on prisma docs, but I cannot do this query, every time get an error, so if someone can tell me, how can I do this with an example, I'll be very grateful.
My question is, having this schema, how can I add a song to a playlist? there are two models affected by the query, song (where i am trying to add) and playlist.
My schema:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
model User {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
email String #unique
firstName String
lastName String
password String
playlists Playlist[]
}
// here
model Song {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
name String
artist Artist #relation(fields: [artistId], references: [id])
artistId Int
playlists Playlist[]
duration Int
url String
}
model Artist {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
songs Song[]
name String #unique
}
// here
model Playlist {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
name String
songs Song[]
user User #relation(fields: [userId], references: [id])
userId Int
}
I am trying to add the song like this:
let songId = 1;
let playlistId = 1;
let lists;
// get the playlists the song is part of
lists = await prisma.song.findFirst({
select: {
playlists: true
},
where: {
id: +songId
}
})
// get the playlist data i need
const list = await prisma.playlist.findUnique({
where: {
id: playlistId
}
})
// create the array for update with the data
// plus the data I want to add
lists = [ ...lists.playlists, list ]
// trying to update the old array with the new data (lists)
// this is what i'm doing wrong, help please
await prisma.song.update({
where: { id: +songId },
data:{
playlists: lists
}
})
after many tries i finally got what i want if anyone knows a better way please tell me, i want to learn, for now this is my solution:
i need to send each value as id: playlistId
const song = await prisma.song.findUnique({
select: {
playlists: true
},
where: {
id: +songId
}
})
// get an array of objects, id: playlistId
const songPlaylistsIds = song.playlists.map( playlist => ({id: playlist.id}))
// I prepare the array with the content that already exists plus the new content that I want to add:
const playlists = [...songPlaylistsIds, { id: playlistId}]
await prisma.song.update({
where: { id: +songId },
data:{
playlists: {
// finally for each object in the array i get, id: playlistId and it works.
set: playlists.map( playlistSong => ({ ...playlistSong }))
}
}
})
Problems I had doing this: I was wrong in thinking that it should work as simple as playlist: lists I wanted to change the content to a new one but I couldn't, I needed to send the values one by one.
Another error when I get the content of the playlists. I had the full object but just needed to send the id.
And lastly, in the prisma documentation, there is a method like set, push, but this method doesn't work, at least I don't know how to make push work
Related
I'm making a node api using prisma ORM and i'm trying to update a column which i had set with the type DateTime, here is the model, the column is the deleted_at one
model Employee {
id Int #id #default(autoincrement())
name String
created_at DateTime
deleted_at DateTime
}
how can i change it to the current time in my controller?
the controller looks like this
export const DeleteCompany = async (req:IEmployee, res:Response) => {
const data:ICompany = req
const deletedCompany = await prisma.employee.update({
where: {
id: Number(data.id)
},
data: {
deleted_at: //what should I put here?
}
})
return res.status(200).json(deletedCompany)
}
I've tried using
now()
but it didnt work.
Prisma supports plain javascript dates for setting date fields.
So new Date() should work fine:
deleted_at: new Date()
I have a model called "Setup"
model Setup {
id String #id #default(auto()) #map("_id") #db.ObjectId
userId String? #unique #db.ObjectId
user User? #relation(fields: [userId], references: [id])
contract String[]
legal String[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
In this model i want to store an array like
const contractData = {
id: '729a4839f3dapob44zt2b4b1',
name: 'Example Name',
text: 'Example Text'
}
so in my above model "Setup" i want to store the contractData
prisma.setup.create({
data: {
userId: '6399bc74426f71f2da6e316c',
personal: [],
contract: contractData,
legal: []
}
})
Unfortunately, this not work.
How can i define an Object for contract and store this in my database?
If you want to store a raw JSON, check out this guide: https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields
You will want to use the Json in Prisma in order to be able to store a raw JSON object (or multiple JSON objects as an array.)
model Setup {
id String #id #default(auto()) #map("_id") #db.ObjectId
userId String? #unique #db.ObjectId
user User? #relation(fields: [userId], references: [id])
contract Json[]
legal String[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
Your Prisma prisma.setup.create query would basically be the exact same. Note that querying for what's in this JSON will be trickier - I would recommend creating a new model and then connecting it to the Setup model, but that if that isn't an option you can still perform some limited queries on the contract field.
Docs: https://www.prisma.io/docs/concepts/components/prisma-client/working-with-fields/working-with-json-fields#filter-on-a-json-field
In order to store an object in the contract field, you will need to change the type of the contract field from String[] to Object[].
model Setup {
id String #id #default(auto()) #map("_id") #db.ObjectId
userId String? #unique #db.ObjectId
user User? #relation(fields: [userId], references: [id])
contract Object[]
legal String[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
store an object in the contract field like
prisma.setup.create({
data: {
userId: '6399bc74426f71f2da6e316c',
personal: [],
contract: [contractData],
legal: []
}
})
contract field is now an array, so you will need to pass the object as an element of the array, like [contractData]
On my solid-js application, it is possible for the user to create posts and add likes to them. I would like the posts created on my application to be ordered according to the number of likes obtained in descending order like on reddit.
Here is my prisma schema:
model Post {
id String #id #default(uuid())
content String?
author User #relation(fields: [authorId], references: [id], onDelete: Cascade)
authorId String
likes User[] #relation("_UsersPostsLike")
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
}
For this I wrote the following code:
const posts = await db.post.findMany({
where: {
authorId: currentUser.id,
},
include,
orderBy: {
_count: {
select: {
likes: true,
},
} :"desc",
},
});
But instead it gives me rather syntax errors.
I tried to see if it would work in ascending order, so I edited my code like this:
orderBy: {
_count: {
select: {
likes: true,
},
}
},
it didn't give me any syntax errors but that order is not taken into account.
I don't understand why it doesn't work even with this syntax yet I was sure the syntax was valid.
I am creating a basic crud api with nodejs and prisma. My Schema is as follows:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL")
}
model Category {
id String #unique #default(cuid())
title String
description String
products Product[]
}
model Product {
id String #unique #default(cuid())
title String
description String
price Float
createdAt DateTime #default(now())
updatedAt DateTime?
category Category? #relation(fields: [categoryId], references: [id])
categoryId String?
}
I am trying to make the products field in the Category model optional. But Prisma doesn't allow that. But I want my users to create a category even without creating a post or vice-versa. How can I get around this?
According to the Prisma documentation, lists cannot be optional: https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#remarks-5
However, the products field not being optional does not mean that it cannot be an empty when a new Category is created:
await prisma.category.create({
data: {
title: 'books',
description: 'books',
products: {},
}
})
Then you can create or connect the product later:
await prisma.category.update({
where: {
id: "category-id"
},
data: {
products: {
connect: {
id: "product-id"
}
}
}
})
I need help working through this error. I have a one-to many-self-relationship that dictates all the comments/children a post will have. see schema below.
model Post {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
description String
postedBy User? #relation(fields: [postedById], references: [id])
postedById Int?
votes Vote[]
comments Post[] #relation(name: "comment")
parent Post? #relation(name: "comment", fields: [parentId], references: [id])
parentId Int? #default(0)
}
As you can see, the parentId defaults to zero. I always want the root post to have a parentId of zero to signify that it is a root post because there is no Post with Id 0 for the foreign key to reference.
When I added the one-many-self-relationship with default 0 my prisma populated correctly, ignoring foreign-key errors in my db as seen below.
The parent field is null? or undefined? because the parentId = 0 doesn't exist. That is good because those are root posts. The problem is when I try and make a post mutation using gql I get a foreign key error because there is no post with id 0. See mutation below.
const { userId, prisma } = context;
if (userId === null) throw new Error("Not Authenticated");
const newPost = await prisma.post.create({
data: {
description: args.description,
postedBy: { connect: { id: userId } },
parent: { connect: { id: args.parentId } },
},
});
context.pubsub.publish("NEW_POST", newPost);
return newPost;
}
if I replace args.parentId = 0 I will get the foreign key error in gql, if args.parentId = 1 I will not get an error but the post is no longer considered a root post (bad).
can someone please offer me some guidance with this issue? I would like to ignore the foreign key error if possible.
I have looked into the referential actions (seen below) to set a default on post but I don't think my use case is the purpose of referential actions so I am not sure where to look...
model Post {
id Int #id #default(autoincrement())
title String
authorUsername String? #default("anonymous")
author User? #relation(fields: [authorUsername], references: [username], onUpdate: SetDefault)
}