how to create a optional list field in prisma - javascript

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"
}
}
}
})

Related

How do i store custom object in prisma schema?

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]

How to order the posts according to the number of likes obtained in a solid-js application?

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.

Prisma - GroupBy relation (e.g "Most used Hashtags")

I would like to show the "Most used Hashtags” in my app.
It's just a simple many-to-many relation:
model Post {
id Int #id #default(autoincrement())
title String #db.VarChar(255)
description String #db.VarChar(255)
hashtags PostHashtag[]
}
model PostHashtag {
post Post #relation(fields: [postId], references: [id])
postId Int
hashtag Hashtag #relation(fields: [hashtagId], references: [id])
hashtagId Int
##id([postId, hashtagId])
##unique([postId, hashtagId])
}
model Hashtag {
id Int #id #default(autoincrement())
name String #db.VarChar(24)
posts PostHashtag[]
}
I cannot really find a way to groupBy the "name" field of the "Hashtag" in the PostHashtag table.
My goal is a query which returns me the top 15 used hashtags.
And unfortunately the docs won't help me with this.
This will return the top 15 used hashtags by ordering with posts counts, with the counts included in the result:
const topHashtags = await prisma.hashtag.findMany({
take: 15,
orderBy: {
posts: { _count: 'desc' },
},
include: {
_count: {
select: { posts: true },
},
},
});
Was easier than I thought:
return await prisma.hashtag.groupBy({
by: ['name'],
_count:{
name: true
},
orderBy: {
_count: {
name: 'desc',
}
}
})

Prisma, update scalarList/array

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

How to save multiple tables related to each other with Prisma

I'm working on a NestJS project and I have two tables (TABLE_1 and TABLE_2), TABLE_1 schema looks like this:
model TABLE 1 {
id String #id #default(uuid())
secondaryfield String #unique #map("secondary_field") #db.VarChar(12)
table_2 Table_2[]
}
And table 2:
model TABLE 2 {
id String #id #default(uuid())
table_1_id String #unique #map("secondary_field") #db.VarChar(12)
table_1 Table_1 #relation(fields: [table_1_id], references: [id])
}
Since there's a FK on my table_2 that depends on table_1, and both of them will be saved at the same time, is there any way that allows Prisma to deal with this and save multiple fields (not only two like the example) with multiple relations between them? I'm using createMany() method as I usually save dozens of those at the same time.
You can try out the following:
prisma.table2.create({
data: {
table1: {
createMany: {
data: [
{
secondaryfield: 'table1-1',
},
{
secondaryfield: 'table1-2',
},
],
}
}
}
})
More info here

Categories