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]
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 my schema.prisma file I have those 2 models:
model User {
id String #id #default(uuid()) #db.Uuid
firstName String #map("first_name") #db.VarChar(40)
lastName String #map("last_name") #db.VarChar(40)
email String #unique #db.Citext
phone String #db.VarChar(60)
dialCode String #map("dial_code") #db.VarChar(5)
password String #db.VarChar(500)
twoFactorSecret String #db.VarChar(300)
roleId String #map("role_id") #db.Uuid
role Role #relation(fields: [roleId], references: [id])
customPermissions UserCustomPermission[]
updatedAt DateTime #default(now()) #updatedAt #map("updated_at") #db.Timestamptz(6)
createdAt DateTime #default(now()) #map("created_at") #db.Timestamptz(6)
##unique([dialCode, phone], map: "phone_number_unique")
##map("user")
UserAction UserAction[]
}
model UserAction {
id String #id #default(uuid()) #db.Uuid
userId String #map("user_id") #db.Uuid
method String #db.VarChar(120)
url String #db.VarChar(120)
userAgent String #db.VarChar(120)
requestBody Json?
responseBody Json?
user User #relation(fields: [userId], references: [id])
updatedAt DateTime #default(now()) #updatedAt #map("updated_at") #db.Timestamptz(6)
createdAt DateTime #default(now()) #map("created_at") #db.Timestamptz(6)
}
It is supposed to be one-to-many connection, but I have this warning in terminal when trigger function that creates record:
async createRecord({userId, method, url, userAgent, requestBody, responseBody}) {
return this.prisma.userAction.create({
data: {userId, method, url, userAgent, requestBody, responseBody}
})
}
And this warning:
+ user: {
+ create?: UserCreateWithoutUserActionInput | UserUncheckedCreateWithoutUserActionInput,
+ connectOrCreate?: UserCreateOrConnectWithoutUserActionInput,
+ connect?: UserWhereUniqueInput
+ },
? id?: String,
? updatedAt?: DateTime,
? createdAt?: DateTime
}
}
Argument user for data.user is missing.
Note: Lines with + are required, lines with ? are optional.
Actually, everything seems to be working fine, but I am wondering on how to fix this. I guess, that connection between 2 tables was created incorrect, but I have never worked with prisma before, so I don't really know where error is.
So, how can I fix this? Thanks in advance!
I faced this error because I passed an undefined value to a foreign key field of one of my models.
In your case, should be checked that createRecord is being invoked with a valid userId.
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 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"
}
}
}
})
I need help working through this error. I have a one-to many-self-relationship that dictates all the comments/children a post will have. see schema below.
model Post {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
description String
postedBy User? #relation(fields: [postedById], references: [id])
postedById Int?
votes Vote[]
comments Post[] #relation(name: "comment")
parent Post? #relation(name: "comment", fields: [parentId], references: [id])
parentId Int? #default(0)
}
As you can see, the parentId defaults to zero. I always want the root post to have a parentId of zero to signify that it is a root post because there is no Post with Id 0 for the foreign key to reference.
When I added the one-many-self-relationship with default 0 my prisma populated correctly, ignoring foreign-key errors in my db as seen below.
The parent field is null? or undefined? because the parentId = 0 doesn't exist. That is good because those are root posts. The problem is when I try and make a post mutation using gql I get a foreign key error because there is no post with id 0. See mutation below.
const { userId, prisma } = context;
if (userId === null) throw new Error("Not Authenticated");
const newPost = await prisma.post.create({
data: {
description: args.description,
postedBy: { connect: { id: userId } },
parent: { connect: { id: args.parentId } },
},
});
context.pubsub.publish("NEW_POST", newPost);
return newPost;
}
if I replace args.parentId = 0 I will get the foreign key error in gql, if args.parentId = 1 I will not get an error but the post is no longer considered a root post (bad).
can someone please offer me some guidance with this issue? I would like to ignore the foreign key error if possible.
I have looked into the referential actions (seen below) to set a default on post but I don't think my use case is the purpose of referential actions so I am not sure where to look...
model Post {
id Int #id #default(autoincrement())
title String
authorUsername String? #default("anonymous")
author User? #relation(fields: [authorUsername], references: [username], onUpdate: SetDefault)
}