Conditional query Prisma assigning a value using date - prisma

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

Related

crud for a many to many relationship in prisma

so, i want to create a memory for a user and add the user to the memory api using prisma. in this user table and memory table are connected by a many to many relationship. They share a common table userMemory.
schema.prisma
model User {
userId String #id #default(uuid())
avatarUrl String?
bio String?
firstName String
lastName String?
dob DateTime
createdAt DateTime #default(now())
modifiedAt DateTime #default(now()) #updatedAt
createdBy String?
modifiedBy String?
followersCount BigInt #default(0)
followingCount BigInt #default(0)
memories UserMemory[]
}
model Memory {
memoryId String #id #default(uuid())
users UserMemory[]
latitude Float?
longitude Float?
createdAt DateTime #default(now())
modifiedAt DateTime #default(now()) #updatedAt
createdBy String?
modifiedBy String?
textHtml String?
mediaUrl String[]
}
This is my user services file
import { Injectable } from '#nestjs/common';
import { GraphQLError } from 'graphql/error';
import { PrismaService } from 'src/prisma/prisma.service';
import {
CreateUserInput,
OrderByInput,
UpdateUserInput,
} from 'src/types/graphql';
#Injectable()
export class UserService {
constructor(private prisma: PrismaService) {}
async create(createUserInput: CreateUserInput) {
try {
let user = await this.prisma.user.create({
data: createUserInput,
});
user = await this.prisma.user.update({
where: { userId: user.userId },
data: {
createdBy: user.userId,
modifiedBy: user.userId,
},
});
return user;
} catch (e) {
throw new GraphQLError('Error Occurred', {
extensions: { e },
});
}
}
}
This is my memories service file
import { Injectable } from '#nestjs/common';
import { GraphQLError } from 'graphql';
import { PrismaService } from 'src/prisma/prisma.service';
import { CreateMemoryInput, UpdateMemoryInput } from 'src/types/graphql';
#Injectable()
export class MemoriesService {
constructor(private prisma: PrismaService) {}
async create({ authorId, ...createMemoryInput }: CreateMemoryInput) {
try {
const user = await this.prisma.user.findUnique({
where: {
userId: authorId,
},
});
const memory = await this.prisma.memory.create({
data: {
...createMemoryInput,
createdBy: authorId,
modifiedBy: authorId,
users: {
create: [
{
user: {
connect: {
userId: authorId,
...user,
},
},
},
],
},
},
include: {
users: true,
},
});
return memory;
} catch (e) {
throw new GraphQLError('Error Occurred', {
extensions: { e },
});
}
}
async findOne(memoryId: string) {
try {
return await this.prisma.memory.findUnique({
where: {
memoryId,
},
include: {
users: true,
},
});
} catch (e) {
throw new GraphQLError('Error Occurred', {
extensions: { e },
});
}
}
}
my users type defination file
scalar Date
scalar URL
scalar Timestamp
scalar UUID
type User {
userId: UUID!
avatarUrl: URL
bio: String
firstName: String!
lastName: String
dob: Date
createdAt: Timestamp
modifiedAt: Timestamp
createdBy: UUID
modifiedBy: UUID
memories: [Memory]
}
input CreateUserInput {
firstName: String!
lastName: String
dob: Date!
}
type Mutation {
createUser(createUserInput: CreateUserInput!): User!
}
my memories type defination file
type Memory {
memoryId: UUID!
users: [User]
latitude: Float
longitude: Float
createdAt: Timestamp
modifiedAt: Timestamp
createdBy: UUID
modifiedBy: UUID
textHtml: String
mediaUrl: [String]
}
input CreateMemoryInput {
authorId: UUID!
latitude: Float
longitude: Float
textHtml: String
mediaUrl: [String]
}
type Query {
memories: [Memory]!
memory(memoryId: UUID!): Memory
}
type Mutation {
createMemory(createMemoryInput: CreateMemoryInput!): Memory!
}
this is my creat mutation query
mutation CreateMemory($createMemoryInput: CreateMemoryInput!) {
createMemory(createMemoryInput: $createMemoryInput) {
createdAt
createdBy
latitude
longitude
mediaUrl
memoryId
modifiedAt
modifiedBy
textHtml
users {
accountType
avatarUrl
bio
createdAt
createdBy
dob
firstName
gender
lastName
modifiedAt
modifiedBy
userId
}
}
}
so whenever i am creating a memoory against a user, i am getting this error, although data is population in data base.
{
"errors": [
{
"message": "Cannot return null for non-nullable field User.firstName.",
"locations": [
{
"line": 43,
"column": 7
}
],
"path": [
"memory",
"users",
0,
"firstName"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Cannot return null for non-nullable field User.firstName.",
" at completeValue (/Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:594:13)",
" at executeField (/Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:489:19)",
" at executeFields (/Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:413:20)",
" at completeObjectValue (/Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:914:10)",
" at completeValue (/Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:635:12)",
" at /Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:696:25",
" at Function.from (<anonymous>)",
" at completeListValue (/Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:676:34)",
" at completeValue (/Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:607:12)",
" at executeField (/Users/sohamnandi/Desktop/Projects/link-yatri-api/node_modules/graphql/execution/execute.js:489:19)"
]
}
}
}
],
"data": {
"memory": {
"createdAt": 1674566005576,
"createdBy": "5a147521-a797-4587-b75f-a07f5b00430e",
"latitude": null,
"longitude": null,
"mediaUrl": [],
"memoryId": "0f2a1a5a-298b-4b8c-a526-7e06e0d4b126",
"modifiedAt": 1674566005576,
"modifiedBy": "5a147521-a797-4587-b75f-a07f5b00430e",
"textHtml": null,
"users": [
null
]
}
}
}

Count or Include filtered relations prisma

I am currently stuck on a problem with my prisma queries.
I have an asset which has a 1 to Many relationship to views. I am trying to perform a findMany() on assets which returns either;
The asset with a list of views created within the last day
Or the asset with a count of views created in the last day
Finally I need to be able to orderBy this count or the count of views in my include statement. (this is what I am stuck on)
return await prisma.asset.findMany({
take: parseInt(pageSize),
skip: (pageSize * pageNumber),
include: {
_count: {
select: {
views: true
},
},
views: {
where: {
createdAt: dateFilter
},
},
likes: {
where: {
createdAt: dateFilter
}
},
transactions: true,
},
orderBy: { views: { _count: 'desc' } }
My queries does correctly return only views in my date range but how do I go about ordering the assets based on the count of these views. I have been stuck for quite some time on this. My raw SQL is not strong enough to write it from scratch at the moment.
If anyone has any ideas, thanks.
Will something like this work?
// First we group the views, with pagination
const groupedViews = await prisma.view.groupBy({
take: 10,
skip: 0,
by: ['postId'],
where: { createdAt: dateFilter },
_count: { postId: true },
orderBy: { _count: { postId: 'desc' } },
});
// Fetch the posts from the grouped views
const _posts = await prisma.post.findMany({
where: {
id: { in: groupedViews.map(({ postId }) => postId) },
},
include: {
_count: { select: { views: true } },
views: { where: { createdAt: dateFilter } },
},
});
// Map the fetched posts back for correct ordering
const posts = groupedViews.map(({ postId }) =>
_posts.find(({ id }) => id === postId)
);
Model:
model Post {
id String #id #default(cuid())
views View[]
}
model View {
id String #id #default(cuid())
createdAt DateTime #default(now())
postId String
post Post #relation(fields: [postId], references: [id])
}
This uses 2 separate queries, but does not require raw sql

How to connect a many to many relationship using Prisma

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

findUnique query returns null for array fields

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

Prevent updating fields with the same value in Prisma

I have a datamodel type for example
type XYZ {
id: ID!
relatedTable: ABC
someValue: String
}
Graphql part:
const createXYZ = gql`
mutation createXYZ(
relatedTableId: ID
someValue: String
) {
createXYZ(
data: {
relatedTableId: $relatedTableId
someValue: $someValue
}
) { ... }
`
const updateXYZ = gql`
mutation updateXYZ(
id: ID!
relatedTableId: ID
someValue: String
) {
updateXYZ(
data: {
relatedTableId: $relatedTableId
someValue: $someValue
},
where: { id: $id }
) { ... }
`
From the forntend I create XYZ record, with a mutation more or less like this:
createXYZ(variables: {
relatedTableId: 1,
someValue: 'cde'
})
server side:
createXYZ: async (obj, args, context, info) => {
return prisma.createXYZ({
data: {
relatedTable: { connect: { id: args.data.relatedTableId } },
someValue: args.data.someValue
}
})
}
Frontend side update looks similar to create
updateXYZ(variables: {
id: 2,
relatedTableId: 1,
someValue: 'cde'
})
On the server side, in order to prevent from updating fields with the same value I need to fetch first XYZ record and compare before updating:
updateXYZ: async (obj, args, context, info) => {
const currentXYZ = await prisma.XYZ({ where: args.where })
return prisma.updateXYZ({
data: {
relatedTable: currentXYZ.relatedTable.id !== args.data.relatedTableId
? { connect: { id: args.data.relatedTableId } }
: undefined,
someValue: currentXYZ.someValue !== args.data.someValue
? args.data.someValue
: undefined
},
where: args.where
})
}
Does Prisma have any automatic way of detecting whether the received field value is the same as the current field value or is fetching and comparing values the only solution to this issue?