I'm providing my solution based on the clarifications you provided in the comments. First I would make the following changes to your Schema.

Changing the schema

model A_User {
  id        Int          @id
  username  String
  age       Int
  bio       String       @db.VarChar(1000)
  createdOn DateTime     @default(now())
  features  A_Features[]
}

model A_Features {
  id          Int      @id @default(autoincrement())
  description String   @unique
  users       A_User[]
}

Notably, the relationship between A_User and A_Features is now many-to-many. So a single A_Features record can be connected to many A_User records (as well as the opposite).

Additionally, A_Features.description is now unique, so it's possible to uniquely search for a certain feature using just it's description.

You can read the Prisma Guide on Relations to learn more about many-to-many relations.

Writing the update query

Again, based on the clarification you provided in the comments, the update operation will do the following:

  • Overwrite existing features in a A_User record. So any previous features will be disconnected and replaced with the newly provided ones. Note that the previous features will not be deleted from A_Features table, but they will simply be disconnected from the A_User.features relation.

  • Create the newly provided features that do not yet exist in the A_Features table, and Connect the provided features that already exist in the A_Features table.

You can perform this operation using two separate update queries. The first update will Disconnect all previously connected features for the provided A_User. The second query will Connect or Create the newly provided features in the A_Features table. Finally, you can use the transactions API to ensure that both operations happen in order and together. The transactions API will ensure that if there is an error in any one of the two updates, then both will fail and be rolled back by the database.


//inside async function
const disconnectPreviouslyConnectedFeatures =  prisma.a_User.update({
    where: {id: 1},
    data: {
        features: {
            set: []  // disconnecting all previous features
        }
    }
})

const connectOrCreateNewFeatures =  prisma.a_User.update({
    where: {id: 1},
    data: {
        features: {
            // connect or create the new features
            connectOrCreate: [
                {
                    where: {
                        description: "'first feature'"
                    }, create: {
                        description: "'first feature'"
                    }
                },
                {
                    where: {
                        description: "second feature"
                    }, create: {
                        description: "second feature"
                    }
                }
            ]
        }
    }
})

// transaction to ensure either BOTH operations happen or NONE of them happen.
await prisma.$transaction([disconnectPreviouslyConnectedFeatures, connectOrCreateNewFeatures ])

If you want a better idea of how connect, disconnect and connectOrCreate works, read the Nested Writes section of the Prisma Relation queries article in the docs.

Answer from Tasin Ishmam on Stack Overflow
🌐
Prisma
prisma.io › home › one-to-many relations › one-to-many relations › one-to-many relations › one-to-many relations › one-to-many relations
One-to-many relations | Prisma Documentation
Mandatory 1-n (must assign User when creating Post): model User { id Int @id @default(autoincrement()) posts Post[] } model Post { id Int @id @default(autoincrement()) author User @relation(fields: [authorId], references: [id]) authorId Int } ... How to define and work with one-to-one relations in Prisma.
🌐
Prisma
prisma.io › home › self-relations › self-relations › self-relations › self-relations › self-relations
Self-relations | Prisma Documentation
How to define and work with many-to-many relations in Prisma. ... Referential actions let you define the update and delete behavior of related models on the database level · One-to-one self-relationsOne-to-many self relationsMany-to-many self relationsMultiple self-relations on same model
Top answer
1 of 2
14

I'm providing my solution based on the clarifications you provided in the comments. First I would make the following changes to your Schema.

Changing the schema

model A_User {
  id        Int          @id
  username  String
  age       Int
  bio       String       @db.VarChar(1000)
  createdOn DateTime     @default(now())
  features  A_Features[]
}

model A_Features {
  id          Int      @id @default(autoincrement())
  description String   @unique
  users       A_User[]
}

Notably, the relationship between A_User and A_Features is now many-to-many. So a single A_Features record can be connected to many A_User records (as well as the opposite).

Additionally, A_Features.description is now unique, so it's possible to uniquely search for a certain feature using just it's description.

You can read the Prisma Guide on Relations to learn more about many-to-many relations.

Writing the update query

Again, based on the clarification you provided in the comments, the update operation will do the following:

  • Overwrite existing features in a A_User record. So any previous features will be disconnected and replaced with the newly provided ones. Note that the previous features will not be deleted from A_Features table, but they will simply be disconnected from the A_User.features relation.

  • Create the newly provided features that do not yet exist in the A_Features table, and Connect the provided features that already exist in the A_Features table.

You can perform this operation using two separate update queries. The first update will Disconnect all previously connected features for the provided A_User. The second query will Connect or Create the newly provided features in the A_Features table. Finally, you can use the transactions API to ensure that both operations happen in order and together. The transactions API will ensure that if there is an error in any one of the two updates, then both will fail and be rolled back by the database.


//inside async function
const disconnectPreviouslyConnectedFeatures =  prisma.a_User.update({
    where: {id: 1},
    data: {
        features: {
            set: []  // disconnecting all previous features
        }
    }
})

const connectOrCreateNewFeatures =  prisma.a_User.update({
    where: {id: 1},
    data: {
        features: {
            // connect or create the new features
            connectOrCreate: [
                {
                    where: {
                        description: "'first feature'"
                    }, create: {
                        description: "'first feature'"
                    }
                },
                {
                    where: {
                        description: "second feature"
                    }, create: {
                        description: "second feature"
                    }
                }
            ]
        }
    }
})

// transaction to ensure either BOTH operations happen or NONE of them happen.
await prisma.$transaction([disconnectPreviouslyConnectedFeatures, connectOrCreateNewFeatures ])

If you want a better idea of how connect, disconnect and connectOrCreate works, read the Nested Writes section of the Prisma Relation queries article in the docs.

2 of 2
2

The TypeScript definitions of prisma.a_User.update can tell you exactly what options it takes. That will tell you why the 'features' does not exist in type error is occurring. I imagine the object you're passing to data takes a different set of options than you are specifying; if you can inspect the TypeScript types, Prisma will tell you exactly what options are available.

If you're trying to add new features, and update specific ones, you would need to specify how Prisma can find an old feature (if it exists) to update that one. Upsert won't work in the way that you're currently using it; you need to provide some kind of identifier to the upsert call in order to figure out if the feature you're adding already exists.

https://www.prisma.io/docs/reference/api-reference/prisma-client-reference/#upsert

You need at least create (what data to pass if the feature does NOT exist), update (what data to pass if the feature DOES exist), and where (how Prisma can find the feature that you want to update or create.)

You also need to call upsert multiple times; one for each feature you're looking to update or create. You can batch the calls together with Promise.all in that case.

const upsertFeature1Promise = prisma.a_User.update({
  data: {
    // upsert call goes here, with "create", "update", and "where"
  }
});
const upsertFeature2Promise = prisma.a_User.update({
  data: {
    // upsert call goes here, with "create", "update", and "where"
  }
});
const [results1, results2] = await Promise.all([
  upsertFeaturePromise1,
  upsertFeaturePromise2
]);
🌐
Prisma
prisma.io › home › relations › relations › relations › relations
Relations | Prisma Documentation
A relation is a connection between two models in the Prisma schema. For example, there is a one-to-many relation between User and Post because one user can have many blog posts:
🌐
Medium
medium.com › @imvinojanv › mastering-data-relationships-a-comprehensive-guide-to-building-prisma-schemas-99e1fe50a91d
Mastering Data Relationships: A Comprehensive Guide to Building Prisma Schemas | by Vinojan Veerapathirathasan | Medium
May 21, 2024 - Prisma provides a robust framework to model and manage relationships between data entities in both relational and non-relational databases. These relationships are crucial in representing how data connects across different parts of your application. Prisma supports several types of relationships: one-to-one, one-to-many, and many-to-many.
🌐
GitHub
github.com › prisma › prisma › discussions › 20887
Multiple one-to-many relations on the same model? · prisma/prisma · Discussion #20887
Mapping an employee hierarchy in Prisma can be achieved using self-relations. You've already correctly implemented the one-to-many self-relation for direct reports and managers. However, for indirect reports, you're trying to use an embedded many-to-many relation which is not supported in Postgres as the error message indicates.
Author   prisma
🌐
StudyRaid
app.studyraid.com › en › read › 11147 › 345638 › one-to-many-relationships
Understand one-to-Many Relationships
January 1, 2025 - One-to-many relationships are a fundamental concept in database design, allowing a single record in one table to be associated with multiple records in another table. In Prisma ORM, these relationships are defined in the Prisma schema using ...
Find elsewhere
🌐
GitHub
github.com › prisma › prisma › discussions › 20876
Create one-to-many and one-to-one relation on same field. · prisma/prisma · Discussion #20876
August 29, 2023 - To create a one-to-many relationship between the User and Post tables, you've already defined the schema correctly with the User having an array of Posts and the Post having a reference to the User. Now, to add the ability for a user to optionally "pin" a post, you can create an additional field in the User table that represents the pinned post.
Author   prisma
🌐
YouTube
youtube.com › watch
Mastering Prisma in Next.js: One-to-Many Relationships - YouTube
🚀 Unlock the power of Prisma's one-to-many relationships! Join us in this in-depth tutorial where we unravel the complexities of managing one-to-many relati...
Published   March 27, 2024
🌐
Medium
medium.com › yavar › prisma-relations-2ea20c42f616
Prisma relations
August 19, 2022 - A relation is a connection between two models in the Prisma schema. ... One-to-one (1–1) relations refer to relations where at most one record can be connected on both sides of the relation.
🌐
GitHub
github.com › prisma › prisma › issues › 12552
Many-to-one or One-way relationships · Issue #12552 · prisma/prisma
March 28, 2022 - I find it problematic that relations can only be modelled as one->many instead of many->one. An example use case: model Post { id String @id User User[] @relation(fields: [userIds], references: [id]) userIds String[] } model User { id String @id likes Post[] @relation(references: [id], fields: [likedPostIds]) likedPostIds String[] } This simple data model would allow me to use prisma's nice Fluent API, and do things like User.likes().
Author   prisma
🌐
GitHub
github.com › prisma › prisma › discussions › 21488
One-to-many relation from multiple models to the same model · prisma/prisma · Discussion #21488
I'm using separate join tables (UserImage and ProductImage) that establish the connections between User or Product entities and the Image entity. This setup ensures that each image is uniquely associated with either a user or a product, fulfilling the one-to-many relationship requirement without code duplication.
Author   prisma
🌐
DEV Community
dev.to › lemartin07 › understanding-one-to-one-relations-with-prisma-orm-3i3m
Understanding One-to-One Relations with Prisma ORM - DEV Community
June 15, 2024 - In a database, a One-to-One relationship means that a record in one table is directly associated with a single record in another table. For example, let's say you have two tables: User and Profile.
Top answer
1 of 1
3

I would suggest creating the schema in the following manner:

model languages {
  language_id             Int                       @id @default(autoincrement())
  language_code           String                    @unique
  translations_categories translations_categories[]
}

model categories {
  category_id             Int                       @id @default(autoincrement())
  category_name           String
  translations_categories translations_categories[]
}

model translations_categories {
  translation_id    Int        @id @default(autoincrement())
  language_id       Int
  category_id       Int
  translation_value String
  categories        categories @relation(fields: [category_id], references: [category_id])
  language          languages  @relation(fields: [language_id], references: [language_id])

  @@unique([language_id, category_id])
}

The reason for this is that language_code will always be unique for each language so having the @unique would make it much easier to create or update the category.

So you could create/update the category as follows:

let data = {
  id: 2,
  identifier: 'TEST-1',
  translations: {
    de: 'german',
    en: 'english',
    fr: 'france',
    it: 'italian',
  },
}

let translations = Object.entries(data.translations).map(([key, val]) => ({
  language: {
    connectOrCreate: {
      where: { language_code: key },
      create: { language_code: key },
    },
  },
  translation_value: val,
}))

await prisma.categories.upsert({
  where: { category_id: data.id },
  create: {
    category_name: data.identifier,
    translations_categories: { create: translations },
  },
  update: {
    category_name: data.identifier,
    translations_categories: { create: translations },
  },
})
🌐
Stack Overflow
stackoverflow.com › questions › 72485778 › prisma-specific-one-to-many-relation
database - Prisma specific one to many relation - Stack Overflow
What I want is fetch the challengeScores of a specific user for specific address where isGasScore is true and where score is the lowest. I want to do the same thing for isByteScore is true and score is the lowest. I also want to fetch for the same specific address the 5 lowest scores (for any users) where isByteScore is true and where is isGasScore is true. Is it doable in one call?
🌐
Prisma
prisma.io › home › many-to-many relations › many-to-many relations › many-to-many relations › many-to-many relations › many-to-many relations
Many-to-many relations | Prisma Documentation
// Find posts by category IDs const posts = await prisma.post.findMany({ where: { categoryIDs: { hasSome: [id1, id2] } }, }); // Find posts by category name const posts = await prisma.post.findMany({ where: { categories: { some: { name: { contains: "Servers" } } } }, }); ... How to define and work with one-to-many relations in Prisma.
Top answer
1 of 1
1

If two fields on a model are relational fields that refer to the same model (Team in this case), you need to prove the name argument to @relation.

Documentation: https://www.prisma.io/docs/reference/api-reference/prisma-schema-reference#relation

In your schema, you would need to specify the name of the relationship like this:

model Match {
  id            String @id @default(uuid())
  tournament_id String
  team_one_id   String
  team_two_id   String

  tournament Tournament? @relation(fields: [tournament_id], references: [id])
  team_one   Team        @relation(fields: [team_one_id], references: [id], name: "matches_team_one")
  team_two   Team        @relation(fields: [team_two_id], references: [id], name: "matches_team_two")

  @@map("matches")
}

model Team {
  id       String @id @default(uuid())
  owner_id String
  matchesTeamOne Match[] @relation(name: "matches_team_one")
  matchesTeamTwo Match[] @relation(name: "matches_team_two")

  @@map("teams")
}

This doesn't really work at scale because you NEED to define two separate relation fields on the Match and Team model. Why not define the teams field as an array on Match so you only need to do it once?

model Match {
  id            String @id @default(uuid())
  tournament_id String
  team_one_id   String
  team_two_id   String

  tournament Tournament? @relation(fields: [tournament_id], references: [id])
  teams Team[]

  @@map("matches")
}

model Team {
  id       String @id @default(uuid())
  owner_id String
  matches  Match[]

  @@map("teams")
}

The caveat with this solution is that you have to validate at your backend level that the teams field only ever has 2 connected teams, no more and no less. But it makes the relationship more transparent to developers and easier to manage under the hood.