Disconnecting Many-to-Many Relationships in Prisma + MySQL - javascript

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

Related

Prisma assigning types that I did not delcare

I have a many to many relationship between Post and Upload and prisma is claiming upload.posts is of type never. Due to this I cannot query a relationship I need. I am not sure why Prisma is assigning type never to this. See the below findFirst statement I am trying to use to connect a upload to a post.
await prisma.upload.findFirst({
where: {
id: upload.id,
},
select: {
type: true,
},
// prisma claims posts is Type never
posts: {
connect: {
id: post.id
}
}
});
Schema for relationships
model Upload {
id Int #id #default(autoincrement())
posts Post[]
}
model Post {
id Int #id #default(autoincrement())
uploads Upload[]
}
Take a look at the Prisma documentation to see how you can use findFirst:
https://www.prisma.io/docs/concepts/components/prisma-client/crud#get-the-first-record-that-matches-a-specific-criteria
You cannot pass posts as a top-level argument to findFirst. You can't make changes to data as you are querying for it, if that is what you are trying to do.
await prisma.upload.findFirst({
where: {
id: upload.id,
},
// REMOVED: "type", your model does not have a "type" field
select: {
id: true,
}
// REMOVED: "posts"
});

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.

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

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

Is it possible in sequelize to query based on an association?

I modelled a data structure where I have a n:m relation between "Rooms" and "Users".
Now I want to delete / destroy a room.
Therefore I want to check if the deleting user is in the room.
I have the username and the roomid.
How can I accomplisch that in one Query.
Basically my question is of it possible to do something like that in a query:
Room.destroy({
where: {
//username in users
users: {$contains: { username: "some username" }}
}
})
Here users is an "Association" to my users.
Considering your users model is defined as User,
this may helps you (or at least gives you a start point):
Room.destroy({
include: [{
model: User,
through: {
where: {username: "some username"}
}
}]
});
This is described in the n:m querying section in Sequelize documentation:
With Belongs-To-Many you can query based on through relation and
select specific attributes. For example using findAll with through
User.findAll({
include: [{
model: Project,
through: {
attributes: ['createdAt', 'startedAt', 'finishedAt']
where: {completed: true}
}
}]
});

Categories