Prisma allows for establishing one-to-many relationships with itself, enabling complex data connections

I am in the process of developing a simple app similar to Tinder using Prisma. In this app, users can swipe left or right to like or dislike other users. I want to be able to retrieve matches (users who also like me) and candidates (all users except myself, my matches, the users I dislike, and the users that dislike me).

Initially, I created a User model along with Likes and Dislikes models

model User {
  id            String     @id
  username      String     @default(value: "")
  age           Int        @default(value: 0)
  bio           String     @default(value: "") @db.VarChar(1000)
}

model Likes {
  id          Int    @id @default(autoincrement())
  userId      String
  likedUserId String
}

model Dislikes {
  id             Int    @id @default(autoincrement())
  userId         String
  dislikedUserId String
}

I then wrote some complex SQL statements and executed them using queryRaw

While it worked, I realized I might not be utilizing Prisma effectively as I was mainly translating SQL to Prisma syntax. This led me to revise my model to include the following changes

model User {
  id            String     @id
  username      String     @default(value: "")
  age           Int        @default(value: 0)
  bio           String     @default(value: "") @db.VarChar(1000)
  liked         User[]     @relation("LikedUserToUser")
  disliked      User[]     @relation("DislikedUserToUser")
}

This modification prompted my IDE to suggest adding the opposite relation or running prisma format. After making those adjustments, my model looked something like this

model User {
  id           String     @id
  username     String     @default(value: "")
  age          Int        @default(value: 0)
  bio          String     @default(value: "") @db.VarChar(1000)
  liked        User[]     @relation("LikedUserToUser")
  disliked     User[]     @relation("DislikedUserToUser")
  userToLike    User?      @relation("LikedUserToUser", fields: [userId], references: [id])
  userToDislike User?      @relation("DislikedUserToUser", fields: [userId], references: [id])
  userId       String?
}

At this point, the functionality seemed to be working smoothly. I could 'like' a user with

const user = await prisma.user.update({
    where: { id: '1' },
    data: {
      liked: {
        connect: { id: '2' },
      },
    },
  })

When querying for user '1' including their likes, the output was as follows

{
  id: '1',
  username: 'Cheryl',
  age: 36,
  bio: 'ornare, libero at auctor ullamcorper',
  userId: null,
  liked: [
    {
      id: '2',
      username: 'Daphne',
      age: 57,
      bio: 'at sem molestie sodales',
      userId: '1'
    }
  ]
}

My current challenge lies in performing more intricate queries such as identifying matches and candidates. Any suggestions?

Answer №1

Make sure your schema matches the following structure:

model User {
  id             String  @id
  username       String  @default(value: "")
  age            Int     @default(value: 0)
  bio            String  @default(value: "")
  liked          User[]  @relation("likedUsers")
  disliked       User[]  @relation("dislikedUsers")
  likedUser      User?   @relation("likedUsers", fields: [likedUserId], references: [id])
  likedUserId    String?
  dislikedUser   User?   @relation("dislikedUsers", fields: [dislikedUserId], references: [id])
  dislikedUserId String? @map("userId")
}

To perform queries like user 1 liking user 2, use the following code:

const user = await prisma.user.update({
    where: { id: '1' },
    data: {
      liked: {
        connect: { id: '2' },
      },
    },
})

You can easily fetch the users that user 1 liked with nested reads as shown below:

const user = await prisma.user.findUnique({
    where: { id: '1' },
    include: { liked: true }
})

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Leveraging the Angular (2) routerLinkActive directive to handle dynamic routes

Although my current approach works, I believe there may be a more efficient way to implement this in Angular. The situation is as follows: Imagine nested, inflected paths like /logos and /logo/:id The markup below functions as intended: <li class ...

Determine the actual execution time of select queries in MySQL

When executing a SELECT query like the one below in MySQL command line. SELECT * FROM MASTER LIMIT 1000; The output shows: 1000 rows in set <0.00 sec> Despite the fact that the query actually takes over 1.5 seconds to complete. Can someone exp ...

Angular2 Navigation: Redirecting to a dynamically constructed route

To start, I need to automatically redirect to today's date as the default. Below is the routing configuration I currently have set up: import { CALENDAR_ROUTE } from './_methods/utils'; export const appRoutes: Routes = [ { path: Cal ...

Cannot trigger event ascn.onchange does not exist as a function

Need to trigger the onChange function and pass parameters within it. Here's what I have tried: setTimeout(function() { document.getElementById(input.key)?.onchange({}) }, 200); Encountering the following error message: cn.onchange is not a function ...

Why isn't the constraint satisfied by this recursive map type in Typescript?

type CustomRecursiveMap< X extends Record<string, unknown>, Y extends Record<string, unknown> > = { [M in keyof X]: M extends keyof Y ? X[M] extends Record<string, unknown> ? Y[M] extends Record<st ...

typescript error: passing an 'any' type argument to a 'never' type parameter is not allowed

Encountering an error with newUser this.userObj.assigned_to.push(newUser);, receiving argument of type 'any' is not assignable to parameter of type 'never' typescript solution Looking for a way to declare newUser to resolve the error. ...

Encountering a 403 error when attempting to upload files to Google Cloud Storage (GCS) using Signed URLs

The main aim is to create a signed URL in the api/fileupload.js file for uploading the file to GCS. Then, retrieve the signed URL from the Nextjs server through the nextjs API at localhost://3000/api/fileupload. Finally, use the generated signed URL to upl ...

Implementing the 'keepAlive' feature in Axios with NodeJS

I've scoured through numerous sources of documentation, Stack Overflow threads, and various blog posts but I'm still unable to make the 'keepAlive' functionality work. What could I be overlooking? Here's my server setup: import ex ...

Retrieving the Total Sum with Mysql and PHP

I'm struggling to calculate the total hours for each month from a specific user and can't seem to get the code right. Any assistance would be greatly appreciated. Here's what I've tried: $sql = "SELECT sum(hours) AS total_Hours FROM ...

Using Firebase: retrieving getAdditionalUserInfo in onCreate of a Firebase Cloud function

Can anyone help me figure out how to retrieve extra data from a SAML login provider in the backend (firebase functions)? I can see the data on the client side but I'm struggling to access it in the backend. I've specified these dependencies for ...

Experiencing a type error within Redux in a React Native project utilizing TypeScript

I am currently working on implementing a feature to store the boolean value of whether a phone number is verified or not. Within my login component: await dispatch(setOTPVerified(data.is_phone_verified)); Action.tsx: export const OTP_VERIFIED = 'OTP ...

Incorporating responsive design with React and Typescript

Trying to utilize React with TypeScript, I aim to dynamically generate components based on a field name // Storing all available components const components = { ComponentA, ComponentB, }; // Dynamically render the component based on fieldName const di ...

Using styled-components in React

I came across this interesting code snippet in the styled-components documentation. Here it is: const Button = styled.button<{ $primary?: boolean; }>` background: ${props => props.$primary ? "#BF4F74" : "white"}; color: ${p ...

Establish a connection between a variable and the selected value of Mat-select using a form

Within my TypeScript code, there exists a variable named type whose value is provided by its parent component. This type value is essentially a string that has the possibility of being empty upon being received from the parent component. Additionally, in t ...

Comparison of performance between using multiple independent loops and a single loop for processing the same dataset

When it comes to exporting data as a PDF, I find myself needing to query a dataset from the database and then navigate through it using loops to manage indexes before exporting. There are various ways the dataset can be manipulated through joins and other ...

Query MySQL database to find timestamps grouped by hour of the day

I have a column in my database labeled updatetime which stores timestamps. An example timestamp would look like this: 2011-02-01 09:00:51. I want to search for all results within a specific hour of the day, regardless of the date. For instance, if I were ...

Consolidating Angular 4 Observable HTTP requests into a single Observable to optimize caching

I am currently working on an Angular 4 application that serves as a dashboard for a system. Several different components within the application make calls to the same REST endpoint using identical TypeScript service classes. While this setup functions corr ...

The i18next module encounters compilation issues when used in a React application with Typescript

In my React-Typescript project, I recently set up i18next for multi-language support. Despite following the official documentation guidelines, I encountered compilation errors when running the app: Property 'changeLanguage' does not exist on type ...

Incorporating XMLHttpRequest in my React Typescript App to trigger a Mailchimp API call, allowing users to easily sign up for the newsletter

My website needs to integrate Mailchimp's API in order for users to subscribe to a newsletter by entering their email into a field. I am looking to implement this without relying on any external libraries. To test out the functionality, I have set up ...

Guidelines for dynamically displaying <router-link> or <a> in Vue based on whether the link is internal or external

<template> <component :is="type === 'internal' ? 'router-link' : 'a'" :to="type === 'internal' ? link : null" :href="type !== 'internal' ? link : null" > <slot /> < ...