Prisma - Unique constraint failed, while there is no unique field in schema - mysql

I am using prisma with three models,
model User {
id String #id #default(cuid())
name String #unique #db.VarChar(35)
email String #unique #db.VarChar(512)
password String #db.VarChar(1024)
details String #default("") #db.VarChar(512)
avatar String #default("/default-avatar.svg") #db.VarChar(150)
activity String #default("Online") #db.VarChar(25)
likes Int #default(0)
suggestions Boolean #default(false)
verified Boolean #default(false)
blockedUsers BlockedUser[]
comments Comment[]
communities Community[]
communityMembers CommunityMember[]
followers Follower[]
friends Friend[]
messages Message[]
posts Post[]
openDMs DM[]
interests UserInterest[]
##map("user")
}
model Community {
id String #id #default(cuid())
title String #unique #db.VarChar(35)
details String #db.VarChar(512)
memberID String?
membersUser User[]
members CommunityMember[]
interests CommunityInterest[]
posts Post[]
##map("community")
}
model CommunityMember {
id String #id #default(cuid())
nickname String?
userID String
communityID String
user User #relation(fields: [userID], references: [id])
community Community #relation(fields: [communityID], references: [id])
owner Boolean
##map("community_member")
}
I have a route in my backend that causes the problem. It creates a new community member table with prisma client and connects the existing user and community to itself, with their ids.
When I do this, I get an error: Unique constraint failed on the constraint: community_member_communityID_key
Here is the code with the creation of the community member:
await prisma.communityMember.create({
data: {
nickname: response.account.name,
user: {
connect: { id: response.account.id }
},
community: {
connect: { id: communityID }
},
owner: false
}
});
I have tried dropping the database and resetting the prisma migrations, with no luck.
When I view the table in mysql, it is apparent that the communityID and userID fields are set as unique, so I think this problem has to do with prisma migrate.
Does anybody know what's happening, and how I can successfully create these fields without them being unique?

Why are you using connect? According to documentation
https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#nested-writes
In nested writes you should use create:
await prisma.communityMember.create({
data: {
nickname: response.account.name,
user: {
create: [
{id: response.account.id}
]
},
community: {
create: [
{id: communityID}
]
},
owner: false
}
})

Related

Prisma Many-to-Many relations with findMany (select)

I am facing an error with Prisma, it does not recognize my request which seems quite simple to me. I need to use "select" to retrieve only certain fields from the table.
Post model:
model Post {
id String #id #default(cuid())
title String
createdAt DateTime? #default(now())
categories CategoriesOnPosts[]
keywords KeywordsOnPosts[]
##map("posts")
}
Category model:
model Category {
id String #id #default(cuid())
name String
createdAt DateTime? #default(now())
posts CategoriesOnPosts[]
##map("categories")
}
CategoriesOnPosts model:
model CategoriesOnPosts {
postId String
categoryId String
post Post #relation(fields: [postId], references: [id])
category Category #relation(fields: [categoryId], references: [id])
##id([postId, categoryId])
##map("categoriesPosts")
}
My Prisma query:
export const getPosts = async () =>
await prisma.post.findMany({
select: {
id: true,
title: true,
categories: {
select: {
name: true,
slug: true,
},
},
createdAt: true,
},
orderBy: [
{
createdAt: 'desc',
},
],
});
I get the following error and I don't know how to fix it.
Unknown field categories for select statement on model Post.
Available options are listed in green.

Prisma Nodejs, relation with ids to get the name

im in trouble to find a way to make this, i want in "serieName" the name of the serie, but always return de id, i dont know what i need to do to make this relation correct, im trying to find a solution, but nothing works.
this is my models:
in Series model, i have a name, and in Figures_table i made a relation with him, and i want to get only the name when i pass the id for the field, so if Series have id: 1, name: "something", i want to show "something" not the id, but only show id.
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model Series {
id Int #unique #default(autoincrement())
serie String
Figures_table Figures_table[]
}
model Manufacturers {
id String #unique
manufacturer String
Figures_table Figures_table[]
}
model Figures_table {
id String #unique
name String #db.LongText
category String #db.LongText
price String #db.LongText
specifications String #db.LongText
releaseInfo String #db.LongText
details String #db.LongText
serieName Int
manufacturerName String #db.VarChar(191)
createdAt DateTime #default(now())
manufacturer Manufacturers #relation(fields: [manufacturerName], references: [id])
series Series #relation(fields: [serieName], references: [id])
Images Images[]
}
model Images {
id Int #unique #default(autoincrement())
link String
figureID String
figureReferenceID Figures_table #relation(fields: [figureID], references: [id])
}
Here's a script which would include the name of the Series while fetching a record from the figures_table
import { PrismaClient, Prisma } from '#prisma/client';
const prisma = new PrismaClient({
log: ['query', 'info', 'warn'],
});
async function main() {
await prisma.figures_table.create({
data: {
category: 'Figures Table Category',
details: 'Figures Table Details',
name: 'Figures Table Name',
id: '1',
price: '1',
releaseInfo: 'Figures Table Release Info',
specifications: 'Figures Table Specifications',
series: {
create: {
serie: 'Series 1',
},
},
manufacturer: {
create: {
manufacturer: 'Manufacturer 1',
id: '1',
},
},
},
});
const figures_table = await prisma.figures_table.findUnique({
where: {
id: '1',
},
include: {
series: true,
},
});
console.log(figures_table);
}
main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});
We used the include section to get the details of Series relation.
Response:
{
id: '1',
name: 'Figures Table Name',
category: 'Figures Table Category',
price: '1',
specifications: 'Figures Table Specifications',
releaseInfo: 'Figures Table Release Info',
details: 'Figures Table Details',
serieName: 1,
manufacturerName: '1',
createdAt: 2022-10-11T12:33:37.768Z,
series: { id: 1, serie: 'Series 1' }
}

Using explicit Many to Many Relation in Prisma

I have the following User and Group models that share a many-to-many relation:
model User {
id String #id #default(uuid())
email String #unique
groups UsersGroups[]
##map("user")
}
model Group {
id String #id #default(uuid())
name String
users UsersGroups[]
##map("group")
}
model UsersGroups {
user User #relation(fields: [userId], references: [id])
userId String #map(name: "user_id")
group Group #relation(fields: [groupId], references: [id])
groupId String #map(name: "group_id")
##id([userId, groupId])
##map("users_groups")
}
I'm having trouble using the connect API in Prisma to connect the users and groups. Here's what I have:
await prisma.group.update({
where: {
id: groupId,
},
data: {
users: {
connect: users.map((user) => ({ id: user.id })),
},
},
include: { users: true },
});
That doesn't work and here is the error I'm getting in the console:
PrismaClientValidationError:
Invalid `prisma.group.update()` invocation:
{
where: {
id: '64ce24c7-3054-42f2-b49f-4cdb52cf1bc7'
},
data: {
users: {
connect: [
{
id: '0b3f4a51-0efe-4b0a-8763-e71bc8091b86'
~~
}
]
}
},
include: {
users: true
}
}
Unknown arg `id` in data.users.connect.0.id for type UsersGroupsWhereUniqueInput. Available args:
type UsersGroupsWhereUniqueInput {
userId_groupId?: UsersGroupsUserIdGroupIdCompoundUniqueInput
}
From that above, it looks as though it's attempting to connect a user with id: '0b3f4a51-0efe-4b0a-8763-e71bc8091b86' (which is a user that exists) to the group with id: '64ce24c7-3054-42f2-b49f-4cdb52cf1bc7' (which also exists).
I'd be very grateful if someone could point out where I'm going wrong as I've been going in circles with this for a while now...
You are using an explicit many-to-many relation, cf. https://www.prisma.io/docs/concepts/components/prisma-schema/relations/many-to-many-relations#explicit-many-to-many-relations
I.e. you have defined the model UsersGroups yourself.
As a consequence, you would have to manage/create the records in this table yourself and connect it with the entry in the third table, e.g. like this (haven't tested it):
prisma.group.update({
where: {
id: groupId,
},
data: {
users: { create: { user: { connect: { id: userId } } } },
},
include: { users: true },
});
or if you want to loop over an list:
prisma.group.update({
where: {
id: groupId,
},
data: {
users: {
create: users.map((user) => ({
user: { connect: { id: user.id } },
})),
},
},
include: { users: true },
});
I would suggest to replace groups UsersGroups[] and users UserGroups[] with
userGroups UsersGroups[] in the schema to make it clearer.
As an alternative to explicit relationships you could try to use implicit many-to-many relations in the schema like this:
model User {
id String #id #default(uuid())
email String #unique
groups Group[]
##map("user")
}
model Group {
id String #id #default(uuid())
name String
users User[]
##map("group")
}
cf. https://www.prisma.io/docs/concepts/components/prisma-schema/relations/many-to-many-relations#implicit-many-to-many-relations

EPERM: operation not permitted error : Prisma . After entering the commands 'npx migrate dev --name init'

I am trying to run Prisma to integrate with MySQL database using node js servers. After migrating the Prisma schema to the MySql database I get the following error on Mac air m1
I have already verified that the DATABASE URL IS CONFIGURED PROPERLY.
I have tried clearing the cache forcefully, reinstalling npm, rebooting the pc, and restarting VsCode.
EPERM: operation not permitted, utime '/Users/apple/.cache/prisma/master/bcc2ff906db47790ee902e7bbc76d7ffb1893009/darwin-arm64/prisma-fmt'
apple#Apples-MacBook-Air servers %
When I try to run the server.js file I get the following error
#prisma/client did not initialize yet. Please run "prisma generate" and try to import it again.
In case this error is unexpected for you, please report it in https://github.com/prisma/prisma/issues
at new PrismaClient (/Users/apple/Desktop/react-i/servers/node_modules/.prisma/client/index.js:3:11)
at Object. (/Users/apple/Desktop/react-i/servers/authenticate.js:7:16)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object. (/Users/apple/Desktop/react-i/servers/server.js:7:18)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
running npx prisma generate gives the first error again
Any help is appreciated
Here is the relevant server code snippet
const { PrismaClient } = require("#prisma/client");
const crypto = require('crypto');
const express = require('express');
const route = express.Router();
const jwt = require('jsonwebtoken');
const prisma = new PrismaClient();
const addUserToDb = async user => {
try {
const newUser = await prisma.users.create({
data: {
email: user.email,
username: user.username,
password: hashPassword(user.password),
isAdmin: true,
},
});
console.log(JSON.stringify(newUser));
} catch (e) {
console.error(e);
return 'problem adding user to db';
}
return 'user added to db';
};
const hashPassword = password => {
let salt = crypto.randomBytes(16).toString('hex');
hashedpwd = crypto.pbkdf2Sync(password, salt, 1000, 64, 'sha512');
console.log(hashedpwd);
return hashedpwd;
};
const generateToken = (user, time = '300s') =>
jwt.sign(user, process.env.ACCESS_TOKEN_SECRET, { expiresIn: time });
route.post('/register', (req, res) => {
let newUser = req.body.userRegister;
const accessToken = jwt.sign(newUser, process.env.ACCESS_TOKEN_SECRET);
res.json({ user: addUserToDb(newUser), token: accessToken });
});
module.exports = route;
//prisma.schema code
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model Users {
id String #id #default(uuid())
username String #unique #db.VarChar(255)
email String? #unique #db.VarChar(255)
password String #db.VarChar(255)
refreshToken String?
passwordResetToken String?
profileImgUrl String?
customers Customers?
role String #default("user")
##map(name: "users")
}
model Services {
id Int #id #default(autoincrement())
orders Orders[]
title String
description String
SAC String? #unique #db.VarChar(255)
##map(name: "services")
}
model Customers {
customers Users #relation(fields: [customerId], references: [id])
customerId String #unique
firstName String
lastName String
phoneNumber Int
address String
State String
Pincode Int
City String?
orders Orders[]
##map(name: "customers")
}
model Orders {
id Int #id #default(autoincrement())
value Float
createdAt DateTime #default(now())
service Services #relation(fields: [serviceId], references: [id])
serviceId Int
customer Customers #relation(fields: [customerId], references: [customerId])
customerId String
##map(name: "orders")
}
model Reviews {
id Int #id #default(autoincrement())
title String #db.VarChar(255)
starRating Int
content String?
##map(name: "reviews")
}
Delete the cached Prisma folder at this directory /Users/apple/.cache/ and reinitialized Prisma to get it working again
What helped me with the problem was to remove /Users/apple/.cache/prisma directory as #Ilamuhil mentioned, but instead of installing prisma globally again from npm or yarn, i've just run prisma migrate dev having it installed only locally in my project, and it worked.

Prisma delete many to many relationship with Composite Key

I have this schema here:
model label {
title String #id #db.VarChar(16)
color String #db.VarChar(16)
labelplaylist labelplaylist[]
}
model labelplaylist {
playlistId Int
labelId String #db.VarChar(16)
label label #relation(fields: [labelId], references: [title])
playlist playlist #relation(fields: [playlistId], references: [id])
##id([playlistId, labelId])
##index([labelId], name: "labelId")
}
model playlist {
id Int #id #default(autoincrement())
createdAt DateTime? #default(now()) #db.DateTime(0)
title String #db.VarChar(100)
labelplaylist labelplaylist[]
##index([userId], name: "userId")
}
And I would like to delete only the relation between the label and the playlist table. I tried it to do like this:
const deleteRelation = await prisma.labelplaylist.delete({
where: {
playlistId_labelId:
},
})
I have the primary key of the label and playlist table, but I don't know how I get the primary key => playlistId_labelId.
Thank's for helping out.
Here's the syntax for queries with composite key
const deleteRelation = await prisma.labelplaylist.delete({
where: {
playlistId_labelId: {
playlistId: playListIdVariable, //replace with appropriate variable
labelId: labelIdVariable, //replace with appropriate variable
},
},
});
You can read more in the get record by compound ID or compound unique identifier subsection of the CRUD Reference Guide in the Prisma docs. This reference shows reading data, but the where condition is similar for delete and update as well.
Since it's an explicit many-to-many relationship, nested deleteMany only deletes relation table records, acting like a disconnect. You can then write your query like that:
await req.db.playlist.update({
data: {
labels: {
deleteMany: {},
},
},
where: {
id: labelId,
},
})
or the other way around.
It won't delete your related table records but only the links between them.