diff --git a/content/200-concepts/100-components/01-prisma-schema/04-data-model.mdx b/content/200-concepts/100-components/01-prisma-schema/04-data-model.mdx index 1401d0a3dc..cf742d158c 100644 --- a/content/200-concepts/100-components/01-prisma-schema/04-data-model.mdx +++ b/content/200-concepts/100-components/01-prisma-schema/04-data-model.mdx @@ -637,6 +637,29 @@ model User { } ``` +By default, the name of this field in Prisma Client queries will be `firstName_lastName`. + +You can also provide your own name for the composite ID using the [`@@id`](/reference/api-reference/prisma-schema-reference#id-1) attribute's `name` field: + +```prisma highlight=7;normal +model User { + firstName String + lastName String + email String @unique + isAdmin Boolean @default(false) + + @@id(name: "fullName", fields: [firstName, lastName]) +} +``` + +The `firstName_lastName` field will now be named `fullName` instead. + + + +Refer to the documentation on [working with composite IDs](/concepts/components/prisma-client/working-with-fields/working-with-composite-ids-and-constraints) to learn how to interact with a composite ID in Prisma Client. + + + ##### @unique fields as unique identifiers In the following example, users are uniquely identified by a `@unique` field. Because the `email` field functions as a unique identifier for the model (which is required by Prisma), it must be mandatory: @@ -826,6 +849,32 @@ You can optionally define a [custom unique constraint name](/concepts/components +By default, the name of this field in Prisma Client queries will be `authorId_title`. + +You can also provide your own name for the composite unique constraint using the [`@@unique`](/concepts/components/prisma-schema/names-in-underlying-database#constraint-and-index-names) attribute's `name` field: + +```prisma highlight=10;normal +model Post { + id String @id @default(auto()) @map("_id") @db.ObjectId + createdAt DateTime @default(now()) + title String + published Boolean @default(false) + author User @relation(fields: [authorId], references: [id]) + authorId String @db.ObjectId + categories Category[] @relation(references: [id]) + + @@unique(name: "authorTitle", [authorId, title]) +} +``` + +The `authorId_title` field will now be named `authorTitle` instead. + + + +Refer to the documentation on [working with composite unique identifiers](/concepts/components/prisma-client/working-with-fields/working-with-composite-ids-and-constraints) to learn how to interact with a composite unique constraints in Prisma Client. + + + #### Composite type unique constraints When using the MongoDB provider in version `3.12.0` and later, you can define a unique constraint on a field of a [composite type](#defining-composite-types) using the syntax `@@unique([compositeType.field])`. As with other fields, composite type fields can be used as part of a multi-column unique constraint. diff --git a/content/200-concepts/100-components/02-prisma-client/030-crud.mdx b/content/200-concepts/100-components/02-prisma-client/030-crud.mdx index 65737ec58a..736b90035d 100644 --- a/content/200-concepts/100-components/02-prisma-client/030-crud.mdx +++ b/content/200-concepts/100-components/02-prisma-client/030-crud.mdx @@ -325,99 +325,6 @@ const user = await prisma.user.findUnique({ }) ``` -### Get record by compound ID or compound unique identifier - - - -**MongoDB does not support `@@id`**
-MongoDB does not support composite IDs, which means you cannot identify a model with a `@@id` attribute. - -
- -The following examples demonstrate how to retrieve records by a compound ID or unique identifier, defined by [`@@id`](/reference/api-reference/prisma-schema-reference#id-1) or [`@@unique`](/reference/api-reference/prisma-schema-reference#unique-1) . - -The following Prisma model defines a compound ID: - -]}> - - -```prisma highlight=6;normal -model TimePeriod { - year Int - quarter Int - total Decimal - - @@id([year, quarter]) -} -``` - - - - - - -To retrieve a time period by this compound ID, use the generated `year_quarter` field, which follows the `fieldName1_fieldName2` pattern: - -]}> - - -```ts -const timePeriod = await prisma.timePeriod.findUnique({ - where: { - year_quarter: { - quarter: 4, - year: 2020, - }, - }, -}) -``` - - - - - - -The following Prisma model defines a compound unique identifier with a custom name (`timePeriodId`) - -]}> - - -```prisma highlight=6;normal -model TimePeriod { - year Int - quarter Int - total Decimal - - @@unique(fields: [year, quarter], name: "timePeriodId") -} -``` - - - - - - -To retrieve a time period by this unique identifier, use the custom `timePeriodId` field: - -]}> - - -```ts -const timePeriod = await prisma.timePeriod.findUnique({ - where: { - timePeriodId: { - quarter: 4, - year: 2020, - }, - }, -}) -``` - - - - - - ### Get all records The following [`findMany`](/reference/api-reference/prisma-client-reference#findmany) query returns _all_ `User` records: diff --git a/content/200-concepts/100-components/02-prisma-client/051-working-with-fields/300-working-with-composite-ids-and-constraints.mdx b/content/200-concepts/100-components/02-prisma-client/051-working-with-fields/300-working-with-composite-ids-and-constraints.mdx new file mode 100644 index 0000000000..3d2f160012 --- /dev/null +++ b/content/200-concepts/100-components/02-prisma-client/051-working-with-fields/300-working-with-composite-ids-and-constraints.mdx @@ -0,0 +1,206 @@ +--- +title: 'Working with compound IDs and unique constraints' +metaTitle: 'Working with compound IDs and unique constraints (Concepts)' +metaDescription: 'How to read, write, and filter by compound IDs and unique constraints.' +tocDepth: 2 +--- + + + +Composite IDs and compound unique constraints can be defined in your Prisma schema using the [`@@id`](/reference/api-reference/prisma-schema-reference#id-1) and [`@@unique`](/reference/api-reference/prisma-schema-reference#unique-1) attributes. + + + +**MongoDB does not support `@@id`**
+MongoDB does not support composite IDs, which means you cannot identify a model with a `@@id` attribute. + +
+ +A composite ID or compound unique constraint uses the combined values of two fields as a primary key or identifier in your database table. In the following example, the `postId` field and `userId` field are used as a composite ID for a `Like` table: + +```prisma highlight=22;normal +model User { + id Int @id @default(autoincrement()) + name String + post Post[] + likes Like[] +} + +model Post { + id Int @id @default(autoincrement()) + content String + User User? @relation(fields: [userId], references: [id]) + userId Int? + likes Like[] +} + +model Like { + postId Int + userId Int + User User @relation(fields: [userId], references: [id]) + Post Post @relation(fields: [postId], references: [id]) + + @@id([postId, userId]) +} +``` + +Querying for records from the `Like` table (e.g. using `prisma.like.findMany()`) would return objects that look as follows: + +```json +{ + "postId": 1, + "userId": 1 +} +``` + +Although there are only two fields in the response, those two fields make up a compound ID named `postId_userId`. + +You can also create a named compound ID or compound unique constraint by using the `@@id` or `@@unique` attributes' `name` field. For example: + +```prisma highlight=7;normal +model Like { + postId Int + userId Int + User User @relation(fields: [userId], references: [id]) + Post Post @relation(fields: [postId], references: [id]) + + @@id(name: "likeId", [postId, userId]) +} +``` + +
+ +## Where you can use compound IDs and unique constraints + +Compound IDs and compound unique constraints can be used when working with _unique_ data. + +Below is a list of Prisma Client functions that accept a compound ID or compound unique constraint in the `where` filter of the query: + +- `findUnique` +- `findUniqueOrThrow` +- `delete` +- `update` +- `upsert` + +A composite ID and a composite unique constraint is also usable when creating relational data with `connect` and `connectOrCreate`. + +## Filtering records by a compound ID or unique constraint + +Although your query results will not display a compound ID or unique constraint as a field, you can use these compound values to filter your queries for unique records: + +```ts highlight=3-6;normal +const like = await prisma.like.findUnique({ + where: { + likeId: { + userId: 1, + postId: 1, + }, + }, +}) +``` + + + +Note composite ID and compound unique constraint keys are only available as filter options for _unique_ queries such as `findUnique` and `findUniqueOrThrow`. See the [section](/concepts/components/prisma-client/working-with-fields/working-with-composite-ids/#where-you-can-use-compound-ids-and-unique-identifiers) above for a list of places these fields may be used. + + + +## Deleting records by a compound ID or unique constraint + +A compound ID or compound unique constraint may be used in the `where` filter of a `delete` query: + +```ts highlight=3-6;normal +const like = await prisma.like.delete({ + where: { + likeId: { + userId: 1, + postId: 1, + }, + }, +}) +``` + +## Updating and upserting records by a compound ID or unique constraint + +A compound ID or compound unique constraint may be used in the `where` filter of an `update` query: + +```ts highlight=3-6;normal +const like = await prisma.like.update({ + where: { + likeId: { + userId: 1, + postId: 1, + }, + }, + data: { + postId: 2, + }, +}) +``` + +They may also be used in the `where` filter of an `upsert` query: + +```ts highlight=3-6;normal +await prisma.like.upsert({ + where: { + likeId: { + userId: 1, + postId: 1, + }, + }, + update: { + userId: 2, + }, + create: { + userId: 2, + postId: 1, + }, +}) +``` + +## Filtering relation queries by a compound ID or unique constraint + +Compound IDs and compound unique constraint can also be used in the `connect` and `connectOrCreate` keys used when connecting records to create a relationship. + +For example, consider this query: + +```ts highlight=6-9;normal +await prisma.user.create({ + data: { + name: 'Alice', + likes: { + connect: { + likeId: { + postId: 1, + userId: 2, + }, + }, + }, + }, +}) +``` + +The `likeId` compound ID is used as the identifier in the `connect` object that is used to locate the `Like` table's record that will be linked to the new user: `"Alice"`. + +Similarly, the `likeId` can be used in `connectOrCreate`'s `where` filter to attempt to locate an existing record in the `Like` table: + +```ts highlight=10-13;normal +await prisma.user.create({ + data: { + name: 'Alice', + likes: { + connectOrCreate: { + create: { + postId: 1, + }, + where: { + likeId: { + postId: 1, + userId: 1, + }, + }, + }, + }, + }, +}) +``` diff --git a/content/200-concepts/100-components/02-prisma-client/051-working-with-fields/index.mdx b/content/200-concepts/100-components/02-prisma-client/051-working-with-fields/index.mdx index 767eb73ceb..725aa182bf 100644 --- a/content/200-concepts/100-components/02-prisma-client/051-working-with-fields/index.mdx +++ b/content/200-concepts/100-components/02-prisma-client/051-working-with-fields/index.mdx @@ -83,3 +83,7 @@ See: [Working with `Json` fields](working-with-json-fields) ## Working with scalar lists / scalar arrays See: [Working with scalar lists / arrays](working-with-scalar-lists-arrays) + +## Working with composite IDs and compound unique constraints + +See: [Working with composite IDs and compound unique constraints](working-with-composite-ids-and-constraints)