How to save multiple tables related to each other with Prisma - javascript

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

Related

Disconnecting Many-to-Many Relationships in Prisma + MySQL

I am so completely lost. I have an explicit many to many relation: Users can have multiple Lists, but lists can be owned by multiple users:
model List {
id String #id #default(cuid())
title String
users UsersOnLists[]
}
model User {
id String #id #default(cuid())
name String
lists UsersOnLists[]
}
model UsersOnLists {
id String #id #default(cuid())
order Int
user DictItem? #relation(fields: [userId], references: [id])
userId String?
list List? #relation(fields: [ListId], references: [id])
listId String?
}
Now I'd like to connect a list to a user:
prisma.list.update({
where: {
id: input.id
},
data: {
users: {
create: [{
order: 123,
user: {
connect: {
id: "abcd-123",
}
}
}],
}
}
});
This works.
However, I don't know how to go about disconnecting many-to-many relations in prisma? Say I want to disconnect the user again from the list? How would I do this?
prisma.list.update({
where: {
id: input.id
},
data: {
users: {
disconnect: [{
user: {
disconnect: {
id: "abcd-123",
}
}
}],
}
}
});
This doesn't work.
I also can't find much in the prisma docs about disconnecting. Any ideas?
I guess I could jus delete the row from the Relations-Table, but this doesn't feel as clean and I guess I would still have the old ids in the user & list tables? I would prefer using disconnect, if this is the recommended method for that.
Are you getting a specific error? If you are using a code editor/IDE with TypeScript hinting, it should be giving you a specific error(s) about what's going on. If not that, then the command line should be giving you errors when you attempt to run an operation.
Docs: https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#disconnect-a-related-record
The "disconnect" operation cannot disconnect deeply-nested relations. It only disconnects documents directly connected to the model in question. In your situation, you can only disconnect a UserOnList from a List, but you cannot also disconnect User from UserOnList in the same operation.
prisma.list.update({
where: {
id: input.id
},
data: {
users: {
disconnect: [{
id: "ID_OF_UsersInList_MODEL_HERE"
}],
}
}
});
Also - you don't need the UsersInList table. Prisma can manage the "join" table under the hood for you if you don't need any extra information or data on that model. Check out the docs here if you want Prisma to manage this table on its own: https://www.prisma.io/docs/concepts/components/prisma-schema/relations/many-to-many-relations

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 get data with foreign key in sqlite DB

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

how to create a optional list field in prisma

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

Prisma: how to exclude properties from generated types

EDIT
there's a hidden danger in hiding fields in the TS definitions: the fields will not be accessible during development with intellisense, but the full object with "hidden" fields can be accidentally sent in a response, potentially exposing sensitive data.
I'm building my app using Prisma to connect to the DB (Next.js app). I'm having some trouble with the auto generated Typescript definitions.
I'm following the docs but I can't figure out how to select a subset of fields from Post. In their example:
import { Prisma } from '#prisma/client'
const userWithPosts = Prisma.validator<Prisma.UserArgs>()({
include: { posts: true }, // -> how can I exclude some fields from the Post type?
})
type UserWithPosts = Prisma.UserGetPayload<typeof userWithPosts>
Imagine Post being as follows (simplified):
model Post {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
title String
published Boolean #default(false)
author User #relation(fields: [authorId], references: [id])
authorId Int
}
I'd like to exclude some of the auto-generated fields from the Post type, for example createdAt. Basically user.posts[0] type will have all the fields except createdAt.
One solution could be:
const postData = Prisma.validator<Prisma.PostArgs>()({
select: { id: true, title: true, published: true, authorId: true }
})
type UserWithPosts = Omit<Prisma.UserGetPayload<typeof userWithPosts>, 'posts'> & {
posts: postData[]
}
But I was hoping for something a bit cleaner. Any alternatives?
I found a solution: instead of using include use select with a nested select for posts. The problem is that it becomes quite verbose and cumbersome to maintain (every time a field is added on the schema it must be added here as well...)
const userWithPosts = Prisma.validator<Prisma.UserArgs>()({
select: {
email: true,
name: true,
posts: {
select: {
id: true,
title: true,
published: true,
authorId: true
}
}
}
})

Categories