I am trying to create and connect a record in a Prisma many to many relationship, but the connection part is not working for me.
Here are my Prisma models:
model Ingredient {
id Int #id #default(autoincrement())
name String
createdAt DateTime #default(now())
calories Int
protein Int
fat Int
carbs Int
netCarbs Int
metricQuantity Int
metricUnit String
imperialQuantity Int
imperialUnit String
recipes IngredientsOnRecipes[]
categories CategoriesOnIngredients[]
}
model IngredientCategory {
id Int #id #default(autoincrement())
name String
ingredients CategoriesOnIngredients[]
}
model CategoriesOnIngredients {
ingredient Ingredient #relation(fields: [ingredientId], references: [id])
ingredientId Int // relation scalar field (used in the `#relation` attribute above)
ingredientCategory IngredientCategory #relation(fields: [ingredientCategoryId], references: [id])
ingredientCategoryId Int // relation scalar field (used in the `#relation` attribute above)
assignedAt DateTime #default(now())
##id([ingredientId, ingredientCategoryId])
}
Here is the primsa query I am running:
const ingredient = await prisma.ingredient.create({
data: {
name: title,
metricQuantity: parseInt(quantityMetric),
metricUnit: unitMetric,
imperialQuantity: parseInt(quantityImperial),
imperialUnit: unitImperial,
calories: parseInt(calories),
netCarbs: parseInt(netCarbs),
carbs: parseInt(carbs),
protein: parseInt(protein),
fat: parseInt(fat),
categories: {
ingredientcategory: {
connect: { id: parseInt(categoryId) },
},
},
},
});
Creating a new ingredient works perfectly, but when I add this section:
categories: {
ingredientcategory: {
connect: { id: parseInt(categoryId) },
},
},
I get the following error:
Unknown arg ingredientcategory in data.categories.ingredientcategory for type CategoriesOnIngredientsCreateNestedManyWithoutIngredientInput. Did you mean createMany? Available args:
type CategoriesOnIngredientsCreateNestedManyWithoutIngredientInput {
create?: CategoriesOnIngredientsCreateWithoutIngredientInput | List | CategoriesOnIngredientsUncheckedCreateWithoutIngredientInput | List
connectOrCreate?: CategoriesOnIngredientsCreateOrConnectWithoutIngredientInput | List
createMany?: CategoriesOnIngredientsCreateManyIngredientInputEnvelope
connect?: CategoriesOnIngredientsWhereUniqueInput | List
}
You can try executing the following:
const { PrismaClient } = require('#prisma/client')
const prisma = new PrismaClient()
const saveData = async () => {
const ingredient = await prisma.ingredient.create({
data: {
name: 'ingredient1',
categories: {
create: {
ingredientCategory: {
create: {
name: 'category1',
},
}
}
},
},
select: {
id: true,
name: true,
categories: {
select: {
ingredientId: true,
ingredientCategory: true,
}
},
},
});
console.log(JSON.stringify(ingredient, null, 2));
}
saveData()
And you will have the following:
I managed to get it to work, I had missed create:{} from my Prisma query.
const ingredient = await prisma.ingredient.create({
data: {
name: title,
metricQuantity: parseInt(quantityMetric),
metricUnit: unitMetric,
imperialQuantity: parseInt(quantityImperial),
imperialUnit: unitImperial,
calories: parseInt(calories),
netCarbs: parseInt(netCarbs),
carbs: parseInt(carbs),
protein: parseInt(protein),
fat: parseInt(fat),
categories: {
create: {
ingredientCategory: {
connect: { id: parseInt(categoryId) },
},
},
},
},
});
Related
I've been stuck on this problem for hours.
I'm trying to create an object linked by a many to many relationship.
However, I get this error when the function is invoked:
Unknown arg 0 in data.merchandises.create.0 for type ListingsMerchandisesCreateWithoutListingInput.
Argument merchandise for data.merchandises.create.merchandise is missing.
I don't know where that "0" comes from.
Thank you in advance for your help..
Full log of error:
Invalid `prisma[prismaModel].create()` invocation in
/app/node_modules/prisma-factory/dist/index.js:109:44
106 data = hooks.beforeCreate(data);
107 }
108 const prismaModel = (0, import_camel_case.camelCase)(modelName);
→ 109 let result = await prisma[prismaModel].create({
data: {
type: 'FOR_RENT',
name: 'consequatur',
merchandises: {
create: {
'0': {
merchandise: {
create: {
cosmetic: 'GOOD',
typology: 'NEW',
quantity: 76,
price: 80,
location: {
create: {
name: 'repellat',
line1: '600 Jerde Mews',
line2: 'Apt. 517',
line3: '79414 Lenore Harbor',
line4: 'placeat',
city: 'Port Astridshire',
postalCode: '47459-8067',
state: 'North Carolina',
country: 'Antigua and Barbuda',
other: 'iste'
}
},
user: {
create: {
email: 'Neoma41#gmail.com',
firstName: 'Casimir',
lastName: 'Kub'
}
},
product: {
create: {
name: 'Luxurious Steel Keyboard',
description: 'The Nagasaki Lander is the trademarked name of several series of Nagasaki sport bikes, that started with the 1984 ABC800J',
barcode: 'r0h7w9h1d',
barcodeType: 'EAN13',
brand: 'Bespoke',
model: 'Countach',
lenght: 25,
width: 57,
weight: 11,
capacity: 62,
impactUnit: 'UNIT',
manufacturingImpact: 31,
destructiveImpact: 81
}
}
}
}
},
+ merchandise: {
+ create?: MerchandiseCreateWithoutListingsInput | MerchandiseUncheckedCreateWithoutListingsInput,
+ connectOrCreate?: MerchandiseCreateOrConnectWithoutListingsInput,
+ connect?: MerchandiseWhereUniqueInput
+ }
}
}
}
})
Unknown arg `0` in data.merchandises.create.0 for type ListingsMerchandisesCreateWithoutListingInput.
Argument merchandise for data.merchandises.create.merchandise is missing.
The factory:
import { createFactory } from 'prisma-factory';
import { faker } from '#faker-js/faker';
import {
BarcodeType,
Cosmetic,
ImpactUnit,
Listing,
ListingType,
Prisma,
Typology,
} from '#prisma/client';
const DEFAULT_ATTRIBUTES = {
type: ListingType.FOR_RENT,
name: faker.lorem.word(),
merchandises: {
create: [
{
merchandise: {
create: {
cosmetic: Cosmetic.GOOD,
typology: Typology.NEW,
quantity: Number(faker.random.numeric(2)),
price: Number(faker.random.numeric(2)),
location: {
create: {
name: faker.lorem.word(),
line1: faker.address.streetAddress(),
line2: faker.address.secondaryAddress(),
line3: faker.address.streetAddress(),
line4: faker.lorem.word(),
city: faker.address.city(),
postalCode: faker.address.zipCode(),
state: faker.address.state(),
country: faker.address.country(),
other: faker.lorem.word(4),
},
},
user: {
create: {
email: faker.internet.email(),
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
},
},
product: {
create: {
name: faker.commerce.productName(),
description: faker.commerce.productDescription(),
barcode: faker.random.alphaNumeric(9),
barcodeType: BarcodeType.EAN13,
brand: faker.commerce.productAdjective(),
model: faker.vehicle.model(),
lenght: Number(faker.random.numeric(2)),
width: Number(faker.random.numeric(2)),
weight: Number(faker.random.numeric(2)),
capacity: Number(faker.random.numeric(2)),
impactUnit: ImpactUnit.UNIT,
manufacturingImpact: Number(faker.random.numeric(2)),
destructiveImpact: Number(faker.random.numeric(2)),
},
},
},
},
},
],
},
};
export const ListingFactory = createFactory<Prisma.ListingCreateInput, Listing>(
'listing',
DEFAULT_ATTRIBUTES,
);
concerning schema:
model Listing {
id Int #id #default(autoincrement())
type ListingType
name String
merchandises ListingsMerchandises[]
availability Availability?
category Category? #relation(fields: [categoryId], references: [id])
categoryId Int?
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
deletedAt DateTime?
}
model Merchandise {
id Int #id #default(autoincrement())
cosmetic Cosmetic
typology Typology
quantity Int
price Int
productId Int
product Product #relation(fields: [productId], references: [id])
userId Int
user User #relation(fields: [userId], references: [id])
locationId Int
location Location? #relation(fields: [locationId], references: [id])
listings ListingsMerchandises[]
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
deletedAt DateTime?
}
model ListingsMerchandises {
listingId Int
listing Listing #relation(fields: [listingId], references: [id])
merchandiseId Int
merchandise Merchandise #relation(fields: [merchandiseId], references: [id])
##id([listingId, merchandiseId])
}
I tried several formats, I even tried a connect but without success.
No type errors are thrown
When I'm trying to connect more than one relation to my Profile table I get the following error message:
PrismaClientValidationError:
Invalid `prisma.connection.upsert()` invocation:
{
where: {
id: ''
},
update: {
userOneId: 'clbcb6z58000gyb31ez95frvh',
userTwoId: 'clbcaz4bl000ayb31icwpzphu',
isUserOneApproved: false,
isUserTwoApproved: true,
connectionRequestedOnDate: '2022-12-07T21:48:12.441Z',
connectionAcceptedOnDate: undefined
},
create: {
userOneId: 'clbcb6z58000gyb31ez95frvh',
~~~~~~~~~~~~~
userTwoId: 'clbcaz4bl000ayb31icwpzphu',
~~~~~~~~
isUserOneApproved: false,
isUserTwoApproved: true,
connectionRequestedOnDate: '2022-12-07T21:48:12.441Z',
connectionAcceptedOnDate: undefined,
userOne: {
connect: {
id: 'clbcb6z58000gyb31ez95frvh'
}
},
userTwo: {
connect: {
id: 'clbcaz4bl000ayb31icwpzphu'
}
},
profile: {
connect: {
id: 'clbcb71l2000kyb31cclk79z3'
}
}
}
}
Unknown arg `userOneId` in create.userOneId for type ConnectionCreateInput. Did you mean `userOne`? Available args:
type ConnectionCreateInput {
id?: String
isUserOneApproved: Boolean
isUserTwoApproved: Boolean
connectionRequestedOnDate?: DateTime | Null
connectionAcceptedOnDate?: DateTime | Null
userOne: ProfileCreateNestedOneWithoutUserOneInput
userTwo: ProfileCreateNestedOneWithoutUserTwoInput
profile: ProfileCreateNestedOneWithoutConnectionInput
}
Unknown arg `userTwoId` in create.userTwoId for type ConnectionCreateInput. Did you mean `userTwo`? Available args:
type ConnectionCreateInput {
id?: String
isUserOneApproved: Boolean
isUserTwoApproved: Boolean
connectionRequestedOnDate?: DateTime | Null
connectionAcceptedOnDate?: DateTime | Null
userOne: ProfileCreateNestedOneWithoutUserOneInput
userTwo: ProfileCreateNestedOneWithoutUserTwoInput
profile: ProfileCreateNestedOneWithoutConnectionInput
}
This is how my prisma upsert function is currently defined:
const createOrUpdateRole = await prisma.connection.upsert({
where: { id: id },
update: {
userOneId: userOneId,
userTwoId: userTwoId,
isUserOneApproved,
isUserTwoApproved,
connectionRequestedOnDate,
connectionAcceptedOnDate,
},
create: {
userOneId: userOneId,
userTwoId: userTwoId,
isUserOneApproved,
isUserTwoApproved,
connectionRequestedOnDate,
connectionAcceptedOnDate,
userOne: { connect: { id: userOneId } },
userTwo: { connect: { id: userTwoId } },
profile: { connect: { id: profileId } },
},
});
My expectation when running the function was to connect userOne and userTwo to my Profile table using their respective ids. The reason for that was that I could then query for the connection and then read the profile data for userOne and userTwo.
This is my models defined in schema.prisma:
model Profile {
id String #id #default(cuid())
firstName String?
lastName String?
image String? #db.Text
userId String
user User #relation(fields: [userId], references: [id], onDelete: Cascade)
sensitive Sensitive[]
userOne Connection[] #relation("userOne")
userTwo Connection[] #relation("userTwo")
connection Connection[] #relation("profile")
##index([userId])
}
model Connection {
id String #id #default(cuid())
isUserOneApproved Boolean
isUserTwoApproved Boolean
connectionRequestedOnDate DateTime?
connectionAcceptedOnDate DateTime?
userOneId String
userOne Profile #relation("userOne", fields: [userOneId], references: [id], onDelete: Cascade)
userTwoId String
userTwo Profile #relation("userTwo", fields: [userTwoId], references: [id], onDelete: Cascade)
profileId String
profile Profile #relation("profile", fields: [profileId], references: [id], onDelete: Cascade)
##index([userOneId])
##index([userTwoId])
##index([profileId])
}
If I decide to one connect to only one of them, for instance userOneId using userOne: { connect: { id: userOneId } }, then the function runs as expected, but as soon as I start to define more than one I get the error mentioned above. What have I missed?
The error is pretty self-descriptive:
Unknown arg `userOneId` in create.userOneId for type ConnectionCreateInput
Since you are already passing userOne: {connect: {id: '.....' } } in your Prisma operation, you do not (and should not) also pass userOneId. You just need userOne: {connect..... and userTwo: {connect......
Your operation will end up looking like this:
const createOrUpdateRole = await prisma.connection.upsert({
where: {
id: id
},
update: {
// You can have __either__ `userOneId: 'value'` or `userOne: {connect....` here
// but not both
userOneId: userOneId,
userTwoId: userTwoId,
isUserOneApproved,
isUserTwoApproved,
connectionRequestedOnDate,
connectionAcceptedOnDate,
},
create: {
isUserOneApproved,
isUserTwoApproved,
connectionRequestedOnDate,
connectionAcceptedOnDate,
userOne: {
connect: {
id: userOneId
}
},
userTwo: {
connect: {
id: userTwoId
}
},
profile: {
connect: {
id: profileId
}
},
},
});
In my instance i have a schema joining bonuses to a casino. query works great for data but I am unable to filter via the query itself. The where clause I used appears to be correct but I get an error the stating Object literal may only specify known properties, and 'nodeposit' does not exist in type. But I can query that data.
const data = await prisma.casino_p_casinos.findMany({
where: {
approved: 1,
rogue: 0,
bonuses: {
nodeposit: { gt : 0 },
}
},
select: {
id: true,
clean_name: true,
casino: true,
button: true,
bonuses: {
where: {
nodeposit: { gt: 0 },
},
},
},
take: 14,
});
If I remove the bonus pard in the WHERE clause the query works as expected but I want to grab all bonuses for each casino, but only if the bonuses contains a nodeposit value.
This nis what I want to use.
const data = await prisma.casino_p_casinos.findMany({
where: {
approved: 1,
rogue: 0,
bonuses: {
nodeposit: { gt : 0 },
},
},
select: {
id: true,
clean_name: true,
casino: true,
button: true,
bonuses: true,
},
take: 14,
});
SCHEMA :
model casino_p_casinos {
id Int #id #default(autoincrement())
casino String?
type String?
url String?
bonuses casino_p_bonus[]
model casino_p_bonus {
id Int #id #default(autoincrement())
parent Int
game String?
freespins Int?
freeplay String?
nodeposit Int?
deposit Int?
casino_p_casinos casino_p_casinos #relation(fields: [parent], references: [id])
}
You have a one to many relation, so when you add a where clause, you have one more layer with some, every or none like
const data = await prisma.casino_p_casinos.findMany({
where: {
approved: 1,
rogue: 0,
bonuses: {
// 'some' can be replaced by 'every' or 'none' here
some: {
nodeposit: { gt: 0 }
}
}
},
select: {
id: true,
clean_name: true,
casino: true,
button: true,
bonuses: true
},
take: 14
})
This query will filter casinos where some nodeposit are greater than 0 and return all bonuses, even those who are equals to 0.
And then, if you only want bonuses with nodeposit greater than 0 in casinos that have some, you should do:
const data = await prisma.casino_p_casinos.findMany({
where: {
approved: 1,
rogue: 0,
bonuses: {
// 'some' can be replaced by 'every' or 'none' here
some: {
nodeposit: { gt: 0 }
}
}
},
select: {
id: true,
clean_name: true,
casino: true,
button: true,
bonuses: {
where: {
nodeposit: { gt: 0 }
}
}
},
take: 14
})
I want to find the menus type provided by the restaurant (breakfast type) according to the time now, and the hours to display is on ShowingHours model
I created a Menu model
model Menu {
id String #id #default(cuid())
type String?
branchId String
branch Branch #relation(fields: [branchId], references: [id])
menuCategories MenuCategory[]
ShowingHours ShowingHours? #relation(fields: [showingHoursId], references: [id])
showingHoursId String?
}
and ShowingHours
model ShowingHours {
id String #id #default(cuid())
fromHour Int?
fromMinute Int?
toHour Int?
toMinute Int?
allDay Boolean
menus Menu[]
}
let timeNow = new Date().getHours();
I want to make a condition that if the value of timeNow for example is 9 am, then query a menu that has a inbetween timenow hours from "fromHour" to "toHour"
My approach:
let menuType = await db.menu.findMany({
// between fromhour tohour
where: {
branchId: branchId,
//I WOULD LIKE TO MAKE A CONDITION LIKE: if timeNow >= fromHour && timenow < toHour then fetch
ShowingHours: {
OR: [
{
fromHour: {
in:
}
}
]
}
},
})
You can use the lt and gt comparison operators to form the query.
It could look something like this:
import { PrismaClient } from '#prisma/client';
const prisma = new PrismaClient({
log: [{ level: 'query', emit: 'stdout' }],
});
async function main() {
let timeNow = new Date().getHours();
await prisma.menu.findMany({
where: {
branchId: '1',
ShowingHours: {
AND: [
{
fromHour: {
lt: timeNow,
},
},
{
toHour: {
gt: timeNow,
},
},
],
},
},
});
}
main()
.catch((e) => {
throw e;
})
.finally(async () => {
await prisma.$disconnect();
});
I read the Prisma Relations documentation and it fixed my findMany query which is able to return valid data but I'm getting inconsistent results with findUnique.
Schema
model User {
id Int #id #default(autoincrement())
fname String
lname String
email String
password String
vehicles Vehicle[]
}
model Vehicle {
id Int #id #default(autoincrement())
vin String #unique
model String
make String
drivers User[]
}
Typedefs
const typeDefs = gql'
type User {
id: ID!
fname: String
lname: String
email: String
password: String
vehicles: [Vehicle]
}
type Vehicle {
id: ID!
vin: String
model: String
make: String
drivers: [User]
}
type Mutation {
post(id: ID!, fname: String!, lname: String!): User
}
type Query {
users: [User]
user(id: ID!): User
vehicles: [Vehicle]
vehicle(vin: String): Vehicle
}
'
This one works
users: async (_, __, context) => {
return context.prisma.user.findMany({
include: { vehicles: true}
})
},
However, for some reason the findUnique version will not resolve the array field for "vehicles"
This one doesn't work
user: async (_, args, context) => {
const id = +args.id
return context.prisma.user.findUnique({ where: {id} },
include: { vehicles: true}
)
},
This is what it returns
{
"data": {
"user": {
"id": "1",
"fname": "Jess",
"lname": "Potato",
"vehicles": null
}
}
}
I was reading about fragments and trying to find documentation on graphql resolvers but I haven't found anything relevant that can solve this issue.
Any insight would be appreciated! Thanks!
You need to fix the arguments passed to findUnique. Notice the arrangement of the { and }.
Change
return context.prisma.user.findUnique({ where: { id } },
// ^
include: { vehicles: true}
)
to
return context.prisma.user.findUnique({
where: { id },
include: { vehicles: true }
})