I have an SqlLite database that contains these models
model Product {
id Int #id #unique(map: "sqlite_autoindex_products_1") #default(autoincrement())
label String
description String?
price Int
category_id Int
thumbnail_url String?
categories Category #relation("categoriesToproducts", fields: [category_id], references: [id], onDelete: NoAction, onUpdate: NoAction)
##map("products")
}
model Category {
id Int #id #unique(map: "sqlite_autoindex_categories_1") #default(autoincrement())
index Int?
label String
description String?
products Product[] #relation("categoriesToproducts")
##map("categories")
}
I would like to get products list using :
async allProducts(): Promise<Product[] | null> {
return this.prisma.product.findMany();
}
It returns Products raw data with category_Id field.
I would like to know if there is a way to get category mapped data inside Category table instead of only the id field ?
I have a solution is to get Category table data than loop on products list then replace category_id with the category object.
But I would like to know if there is a better way to map directly data when making request via Prisma client.
In order to query a related model, you have to either use select or include.
prisma.product.findMany({
include: {
categories: true
}
})
// or
prisma.product.findMany({
select: {
categories: true
}
});
Useful documentation links
Relations
Relation queries
Related
I have a Problem using Prisma where I want to findMany with a specific order.
My Model looks like this
model Item {
id Int #id #default(autoincrement())
title String
categoryId Int
category Category #relation(fields: [categoryId], references: [id])
}
model Category {
id Int #id #default(autoincrement())
title String
parentId Int?
parent Category? #relation("categoryRelation", fields: [parentId], references: [id], onDelete: NoAction, onUpdate: NoAction)
subCategories Category[] #relation("categoryRelation")
items Item[]
}
now I want to sort my items by category.parentId but if they dont have a parentId, I want to sort by categoryId. In raw sql I could use something like orderBy coalesce(c.parentId, categoryId)
but I would like to use the prisma way to solve this if there is one
I really know that the problem Is with me and Prisma's one-to-many relationship is working alright but just bear with me please.
1. This is the model's part where I have the problem:
model Product{
Id Int #id #default(autoincrement())
Uuid String #unique #default(uuid())
Title String
BrandName String?
Thumbnails Thumbnail[] // one to many between thumbnail and Product
Price Float
DiscountRate Float?
Category Category #relation(fields: [CategoryId], references: [Id]) // one to many between Category and Product
CategoryId Int // The field containing the ID of the Category of this product
Status Status
Favorite Boolean #default(false)
Stock Int #default(0)
Item Item[] // one to many between Item and Product
}
model Cart{
Id Int #id #default(autoincrement())
Items Item[] // one to many between Item and Cart
}
model Item{
Id Int #id #default(autoincrement())
Product Product #relation(fields: [ProductId], references: [Id]) // one to many between Item and Product
ProductId Int
Quantity Int
Cart Cart? #relation(fields: [CartId],references: [Id]) // one to many between Cart and Item
CartId Int?
}
2. API Code (NextJs)
// addItem.js
import { PrismaClient } from "#prisma/client";
const prisma = new PrismaClient();
export default async (req, res) => {
let PrId = req.body.prodId;
let Qte = req.body.Qte;
let newItem = await prisma.item.create({
data:{
Quantity: Qte,
Product:{
connect:{
Id: PrId,
},
},
Cart:{
connect:{
Id: req.body.cartId
}
}
},
});
return res.status(200).json(newItem);
};
3. Problem's explanation:
Now the thing is that I have multiple carts in the database, each cart contains Items as shown in the model. The real problem is with creating new items:
Adding the first item goes smoothly.
When I wanna add another item which is connected to the same Product I get an error as follows:
Unique constraint failed on the constraint: `Item_ProductId_key`
at RequestHandler.handleRequestError (C:\Users\Bachar\Desktop\First_Freelance\node_modules\#prisma\client\runtime\index.js:30873:13)
at RequestHandler.request (C:\Users\Bachar\Desktop\First_Freelance\node_modules\#prisma\client\runtime\index.js:30856:12)
at async PrismaClient._request (C:\Users\Bachar\Desktop\First_Freelance\node_modules\#prisma\client\runtime\index.js:31836:16)
at async __WEBPACK_DEFAULT_EXPORT__ (webpack-internal:///(api)/./pages/api/addItem.js:12:19)
at async Object.apiResolver (C:\Users\Bachar\Desktop\First_Freelance\node_modules\next\dist\server\api-utils\node.js:367:9)
at async DevServer.runApi (C:\Users\Bachar\Desktop\First_Freelance\node_modules\next\dist\server\next-server.js:474:9)
at async Object.fn (C:\Users\Bachar\Desktop\First_Freelance\node_modules\next\dist\server\next-server.js:736:37)
at async Router.execute (C:\Users\Bachar\Desktop\First_Freelance\node_modules\next\dist\server\router.js:252:36)
at async DevServer.run (C:\Users\Bachar\Desktop\First_Freelance\node_modules\next\dist\server\base-server.js:381:29)
at async DevServer.run (C:\Users\Bachar\Desktop\First_Freelance\node_modules\next\dist\server\dev\next-dev-server.js:724:20) {
code: 'P2002',
clientVersion: '4.5.0',
meta: { target: 'Item_ProductId_key' },
page: '/api/addItem'
}
First of all thanks for anyone who viewed this.
I had a migration before the one above where the ProductId inside the Cart model flagged as #unique, Which I removed in this last migration. The problem was that the database wasn't in sync with this last Prisma Schema even after using npx prisma migrate dev.
I copied the schema file, removed the whole prisma folder, used the npx prisma init to generate a new folder then pasted the schema, migrated and voila!!
Anyways if anyone has an idea on how to do it without removing the schema file It would be a big help to tell me, cuz that would have been one hell of a day if the app was already in production.
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
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
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"
}
}
}
})