Skip to main content

复合类型

warning

复合类型仅适用于 MongoDB。

¥Composite types are only available with MongoDB.

复合类型(在 MongoDB 中称为 嵌入文档)允许你将记录嵌入其他记录中。

¥Composite types, known as embedded documents in MongoDB, allow you to embed records within other records.

我们在 v3.12.0 中制作了复合类型 一般可用。它们之前在 预览 v3.10.0 中可用。

¥We made composite types Generally Available in v3.12.0. They were previously available in Preview from v3.10.0.

本页说明如何:

¥This page explains how to:

  • 包含使用 findFirstfindMany 的复合类型的 find 记录

    ¥find records that contain composite types using findFirst and findMany

  • 使用 createcreateMany 的复合类型 create 新记录

    ¥create new records with composite types using create and createMany

  • 使用 updateupdateMany 的现有记录中的 update 复合类型

    ¥update composite types within existing records using update and updateMany

  • 使用 deletedeleteMany 的复合类型的 delete 记录

    ¥delete records with composite types using delete and deleteMany

示例架构

¥Example schema

我们将在以下示例中使用此架构:

¥We’ll use this schema for the examples that follow:

schema.prisma
generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "mongodb"
url = env("DATABASE_URL")
}

model Product {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String @unique
price Float
colors Color[]
sizes Size[]
photos Photo[]
orders Order[]
}

model Order {
id String @id @default(auto()) @map("_id") @db.ObjectId
product Product @relation(fields: [productId], references: [id])
color Color
size Size
shippingAddress Address
billingAddress Address?
productId String @db.ObjectId
}

enum Color {
Red
Green
Blue
}

enum Size {
Small
Medium
Large
XLarge
}

type Photo {
height Int @default(200)
width Int @default(100)
url String
}

type Address {
street String
city String
zip String
}

在此架构中,Product 模型具有 Photo[] 复合类型,Order 模型具有两个复合 Address 类型。shippingAddress 是必需的,但 billingAddress 是可选的。

¥In this schema, the Product model has a Photo[] composite type, and the Order model has two composite Address types. The shippingAddress is required, but the billingAddress is optional.

使用复合类型时的注意事项

¥Considerations when using composite types

目前在 Prisma 客户端中使用复合类型时存在一些限制:

¥There are currently some limitations when using composite types in Prisma Client:

复合类型上必填字段的默认值

¥Default values for required fields on composite types

从版本 4.0.0 开始,如果在满足以下所有条件时对复合类型执行数据库读取,则 Prisma 客户端会将默认值插入到结果中。

¥From version 4.0.0, if you carry out a database read on a composite type when all of the following conditions are true, then Prisma Client inserts the default value into the result.

状况:

¥Conditions:

  • 复合类型上的字段是 required,并且

    ¥A field on the composite type is required, and

  • 该字段有 默认值,并且

    ¥this field has a default value, and

  • 返回的一个或多个文档中不存在该字段。

    ¥this field is not present in the returned document or documents.

注意:

¥Note:

  • 这与 模型字段 的行为相同。

    ¥This is the same behavior as with model fields.

  • 在读取操作中,Prisma 客户端将默认值插入到结果中,但不会将默认值插入到数据库中。

    ¥On read operations, Prisma Client inserts the default value into the result, but does not insert the default value into the database.

在我们的示例架构中,假设你将必填字段添加到 photo。该字段 bitDepth 有一个默认值:

¥In our example schema, suppose that you add a required field to photo. This field, bitDepth, has a default value:

schema.prisma
...
type Photo {
...
bitDepth Int @default(8)
}

...

假设你随后运行 npx prisma db push更新你的数据库 并使用 npx prisma generate 重新生成 Prisma 客户端。然后,运行以下应用代码:

¥Suppose that you then run npx prisma db push to update your database and regenerate your Prisma Client with npx prisma generate. Then, you run the following application code:

console.dir(await prisma.product.findMany({}), { depth: Infinity })

bitDepth 字段没有内容,因为你刚刚添加了该字段,所以查询返回默认值 8

¥The bitDepth field has no content because you have only just added this field, so the query returns the default value of 8.

** 早期版本 **

¥** Earlier versions **

在 4.0.0 版本之前,Prisma ORM 抛出 P2032 错误,如下:

¥Before version 4.0.0, Prisma ORM threw a P2032 error as follows:

Error converting field "bitDepth" of expected non-nullable
type "int", found incompatible value of "null".

查找包含具有 findfindMany 的复合类型的记录

¥Finding records that contain composite types with find and findMany

可以在 where 操作中按复合类型过滤记录。

¥Records can be filtered by a composite type within the where operation.

以下部分介绍了可用于按单个类型或多个类型进行过滤的操作,并给出了每个类型的示例。

¥The following section describes the operations available for filtering by a single type or multiple types, and gives examples of each.

过滤一种复合类型

¥Filtering for one composite type

使用 isequalsisNotisSet 操作更改单个复合类型:

¥Use the is, equals, isNot and isSet operations to change a single composite type:

  • is:通过匹配复合类型来过滤结果。需要存在一个或多个字段(例如,按送货地址上的街道名称过滤订单)

    ¥is: Filter results by matching composite types. Requires one or more fields to be present (e.g. Filter orders by the street name on the shipping address)

  • equals:通过匹配复合类型来过滤结果。要求所有字段都存在。(例如,按完整送货地址过滤订单)

    ¥equals: Filter results by matching composite types. Requires all fields to be present. (e.g. Filter orders by the full shipping address)

  • isNot:按不匹配的复合类型过滤结果

    ¥isNot: Filter results by non-matching composite types

  • isSet :过滤可选字段以仅包含已设置的结果(设置为值或显式设置为 null)。将此过滤器设置为 true 将排除根本未设置的 undefined 结果。

    ¥isSet : Filter optional fields to include only results that have been set (either set to a value, or explicitly set to null). Setting this filter to true will exclude undefined results that are not set at all.

例如,使用 is 过滤街道名称为 '555 Candy Cane Lane' 的订单:

¥For example, use is to filter for orders with a street name of '555 Candy Cane Lane':

const orders = await prisma.order.findMany({
where: {
shippingAddress: {
is: {
street: '555 Candy Cane Lane',
},
},
},
})

使用 equals 过滤与送货地址中所有字段匹配的订单:

¥Use equals to filter for orders which match on all fields in the shipping address:

const orders = await prisma.order.findMany({
where: {
shippingAddress: {
equals: {
street: '555 Candy Cane Lane',
city: 'Wonderland',
zip: '52337',
},
},
},
})

你还可以对此查询使用简写符号,其中省略 equals

¥You can also use a shorthand notation for this query, where you leave out the equals:

const orders = await prisma.order.findMany({
where: {
shippingAddress: {
street: '555 Candy Cane Lane',
city: 'Wonderland',
zip: '52337',
},
},
})

使用 isNot 过滤没有 zip 代码 '52337' 的订单:

¥Use isNot to filter for orders that do not have a zip code of '52337':

const orders = await prisma.order.findMany({
where: {
shippingAddress: {
isNot: {
zip: '52337',
},
},
},
})

使用 isSet 过滤已设置可选 billingAddress 的订单(设置为某个值或设置为 null):

¥Use isSet to filter for orders where the optional billingAddress has been set (either to a value or to null):

const orders = await prisma.order.findMany({
where: {
billingAddress: {
isSet: true,
},
},
})

过滤多种复合类型

¥Filtering for many composite types

使用 equalsisEmptyeverysomenone 操作来过滤多个复合类型:

¥Use the equals, isEmpty, every, some and none operations to filter for multiple composite types:

  • equals:检查列表的完全相等性

    ¥equals: Checks exact equality of the list

  • isEmpty:检查列表是否为空

    ¥isEmpty: Checks if the list is empty

  • every:列表中的每一项都必须符合条件

    ¥every: Every item in the list must match the condition

  • some:列表中的一项或多项必须符合条件

    ¥some: One or more of the items in the list must match the condition

  • none:列表中的任何项目都不符合条件

    ¥none: None of the items in the list can match the condition

  • isSet :过滤可选字段以仅包含已设置的结果(设置为值或显式设置为 null)。将此过滤器设置为 true 将排除根本未设置的 undefined 结果。

    ¥isSet : Filter optional fields to include only results that have been set (either set to a value, or explicitly set to null). Setting this filter to true will exclude undefined results that are not set at all.

例如,你可以使用 equals 查找具有特定照片列表的产品(所有 urlheightwidth 字段必须匹配):

¥For example, you can use equals to find products with a specific list of photos (all url, height and width fields must match):

const product = prisma.product.findMany({
where: {
photos: {
equals: [
{
url: '1.jpg',
height: 200,
width: 100,
},
{
url: '2.jpg',
height: 200,
width: 100,
},
],
},
},
})

你还可以为此查询使用简写符号,其中省略 equals 并仅指定要过滤的字段:

¥You can also use a shorthand notation for this query, where you leave out the equals and specify just the fields that you want to filter for:

const product = prisma.product.findMany({
where: {
photos: [
{
url: '1.jpg',
height: 200,
width: 100,
},
{
url: '2.jpg',
height: 200,
width: 100,
},
],
},
})

使用 isEmpty 过滤没有照片的产品:

¥Use isEmpty to filter for products with no photos:

const product = prisma.product.findMany({
where: {
photos: {
isEmpty: true,
},
},
})

使用 some 过滤一张或多张照片具有 url"2.jpg" 的产品:

¥Use some to filter for products where one or more photos has a url of "2.jpg":

const product = prisma.product.findFirst({
where: {
photos: {
some: {
url: '2.jpg',
},
},
},
})

使用 none 过滤没有照片具有 url"2.jpg" 的产品:

¥Use none to filter for products where no photos have a url of "2.jpg":

const product = prisma.product.findFirst({
where: {
photos: {
none: {
url: '2.jpg',
},
},
},
})

使用 createcreateMany 创建复合类型记录

¥Creating records with composite types using create and createMany

info

当你使用具有唯一限制的复合类型创建记录时,请注意,MongoDB 不会在记录内强制执行唯一值。了解更多

¥When you create a record with a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. Learn more.

可以使用 set 操作在 createcreateMany 方法中创建复合类型。例如,你可以在 create 中使用 setOrder 中创建 Address 复合类型:

¥Composite types can be created within a create or createMany method using the set operation. For example, you can use set within create to create an Address composite type inside an Order:

const order = await prisma.order.create({
data: {
// Normal relation
product: { connect: { id: 'some-object-id' } },
color: 'Red',
size: 'Large',
// Composite type
shippingAddress: {
set: {
street: '1084 Candycane Lane',
city: 'Silverlake',
zip: '84323',
},
},
},
})

你还可以使用速记符号,省略 set 并仅指定要创建的字段:

¥You can also use a shorthand notation where you leave out the set and specify just the fields that you want to create:

const order = await prisma.order.create({
data: {
// Normal relation
product: { connect: { id: 'some-object-id' } },
color: 'Red',
size: 'Large',
// Composite type
shippingAddress: {
street: '1084 Candycane Lane',
city: 'Silverlake',
zip: '84323',
},
},
})

对于可选类型,例如 billingAddress,你还可以将值设置为 null

¥For an optional type, like the billingAddress, you can also set the value to null:

const order = await prisma.order.create({
data: {
// Normal relation
product: { connect: { id: 'some-object-id' } },
color: 'Red',
size: 'Large',
// Composite type
shippingAddress: {
street: '1084 Candycane Lane',
city: 'Silverlake',
zip: '84323',
},
// Embedded optional type, set to null
billingAddress: {
set: null,
},
},
})

要对 product 包含多个 photos 列表的情况进行建模,你可以一次 set 多个复合类型:

¥To model the case where an product contains a list of multiple photos, you can set multiple composite types at once:

const product = await prisma.product.create({
data: {
name: 'Forest Runners',
price: 59.99,
colors: ['Red', 'Green'],
sizes: ['Small', 'Medium', 'Large'],
// New composite type
photos: {
set: [
{ height: 100, width: 200, url: '1.jpg' },
{ height: 100, width: 200, url: '2.jpg' },
],
},
},
})

你还可以使用速记符号,省略 set 并仅指定要创建的字段:

¥You can also use a shorthand notation where you leave out the set and specify just the fields that you want to create:

const product = await prisma.product.create({
data: {
name: 'Forest Runners',
price: 59.99,
// Scalar lists that we already support
colors: ['Red', 'Green'],
sizes: ['Small', 'Medium', 'Large'],
// New composite type
photos: [
{ height: 100, width: 200, url: '1.jpg' },
{ height: 100, width: 200, url: '2.jpg' },
],
},
})

这些操作也适用于 createMany 方法。例如,你可以创建多个 product,其中每个包含 photos 的列表:

¥These operations also work within the createMany method. For example, you can create multiple products which each contain a list of photos:

const product = await prisma.product.createMany({
data: [
{
name: 'Forest Runners',
price: 59.99,
colors: ['Red', 'Green'],
sizes: ['Small', 'Medium', 'Large'],
photos: [
{ height: 100, width: 200, url: '1.jpg' },
{ height: 100, width: 200, url: '2.jpg' },
],
},
{
name: 'Alpine Blazers',
price: 85.99,
colors: ['Blue', 'Red'],
sizes: ['Large', 'XLarge'],
photos: [
{ height: 100, width: 200, url: '1.jpg' },
{ height: 150, width: 200, url: '4.jpg' },
{ height: 200, width: 200, url: '5.jpg' },
],
},
],
})

更改 updateupdateMany 内的复合类型

¥Changing composite types within update and updateMany

info

当你使用具有唯一限制的复合类型更新记录时,请注意,MongoDB 不会在记录内强制执行唯一值。了解更多

¥When you update a record with a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. Learn more.

可以在 updateupdateMany 方法中设置、更新或删除复合类型。以下部分描述了可用于一次更新单个类型或多个类型的操作,并给出了每个类型的示例。

¥Composite types can be set, updated or removed within an update or updateMany method. The following section describes the operations available for updating a single type or multiple types at once, and gives examples of each.

更改单个复合类型

¥Changing a single composite type

使用 setunsetupdateupsert 操作更改单个复合类型:

¥Use the set, unset update and upsert operations to change a single composite type:

  • 使用 set 设置复合类型,覆盖任何现有值

    ¥Use set to set a composite type, overriding any existing value

  • 使用 unset 取消设置复合类型。与 set: null 不同,unset 完全移除了该字段

    ¥Use unset to unset a composite type. Unlike set: null, unset removes the field entirely

  • 使用 update 更新复合类型

    ¥Use update to update a composite type

  • 使用 upsertupdate 现有复合类型(如果存在),否则使用 set 复合类型

    ¥Use upsert to update an existing composite type if it exists, and otherwise set the composite type

例如,使用 update 将所需的 shippingAddress 更新为 Order 内的 Address 复合类型:

¥For example, use update to update a required shippingAddress with an Address composite type inside an Order:

const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
shippingAddress: {
// Update just the zip field
update: {
zip: '41232',
},
},
},
})

对于可选的嵌入类型,例如 billingAddress,如果不存在,则使用 upsert 创建新记录,如果存在则更新记录:

¥For an optional embedded type, like the billingAddress, use upsert to create a new record if it does not exist, and update the record if it does:

const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
billingAddress: {
// Create the address if it doesn't exist,
// otherwise update it
upsert: {
set: {
street: '1084 Candycane Lane',
city: 'Silverlake',
zip: '84323',
},
update: {
zip: '84323',
},
},
},
},
})

你还可以使用 unset 操作来删除可选的嵌入类型。以下示例使用 unsetOrder 中删除 billingAddress

¥You can also use the unset operation to remove an optional embedded type. The following example uses unset to remove the billingAddress from an Order:

const order = await prisma.order.update({
where: {
id: 'some-object-id',
},
data: {
billingAddress: {
// Unset the billing address
// Removes "billingAddress" field from order
unset: true,
},
},
})

你可以在 updateMany 中使用 filters 来更新与复合类型匹配的所有记录。以下示例使用 is 过滤器来匹配订单列表中送货地址的街道名称:

¥You can use filters within updateMany to update all records that match a composite type. The following example uses the is filter to match the street name from a shipping address on a list of orders:

const orders = await prisma.order.updateMany({
where: {
shippingAddress: {
is: {
street: '555 Candy Cane Lane',
},
},
},
data: {
shippingAddress: {
update: {
street: '111 Candy Cane Drive',
},
},
},
})

更改多种复合类型

¥Changing multiple composite types

使用 setpushupdateManydeleteMany 操作更改复合类型列表:

¥Use the set, push, updateMany and deleteMany operations to change a list of composite types:

  • set:设置复合类型的嵌入列表,覆盖任何现有列表

    ¥set: Set an embedded list of composite types, overriding any existing list

  • push:将值推送到复合类型嵌入列表的末尾

    ¥push: Push values to the end of an embedded list of composite types

  • updateMany:一次更新多个复合类型

    ¥updateMany: Update many composite types at once

  • deleteMany:一次删除多个复合类型

    ¥deleteMany: Delete many composite types at once

例如,使用 push 将新照片添加到 photos 列表中:

¥For example, use push to add a new photo to the photos list:

const product = prisma.product.update({
where: {
id: '62de6d328a65d8fffdae2c18',
},
data: {
photos: {
// Push a photo to the end of the photos list
push: [{ height: 100, width: 200, url: '1.jpg' }],
},
},
})

使用 updateMany 更新 url1.jpg2.png 的照片:

¥Use updateMany to update photos with a url of 1.jpg or 2.png:

const product = prisma.product.update({
where: {
id: '62de6d328a65d8fffdae2c18',
},
data: {
photos: {
updateMany: {
where: {
url: '1.jpg',
},
data: {
url: '2.png',
},
},
},
},
})

以下示例使用 deleteMany 删除 height 为 100 的所有照片:

¥The following example uses deleteMany to delete all photos with a height of 100:

const product = prisma.product.update({
where: {
id: '62de6d328a65d8fffdae2c18',
},
data: {
photos: {
deleteMany: {
where: {
height: 100,
},
},
},
},
})

使用 upsert 更新插入复合类型

¥Upserting composite types with upsert

info

当你创建或更新具有唯一限制的复合类型中的值时,请注意,MongoDB 不会在记录内强制执行唯一值。了解更多

¥When you create or update the values in a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. Learn more.

要创建或更新复合类型,请使用 upsert 方法。你可以使用与上述 createupdate 方法相同的复合操作。

¥To create or update a composite type, use the upsert method. You can use the same composite operations as the create and update methods above.

例如,使用 upsert 创建新产品或将照片添加到现有产品:

¥For example, use upsert to either create a new product or add a photo to an existing product:

const product = await prisma.product.upsert({
where: {
name: 'Forest Runners',
},
create: {
name: 'Forest Runners',
price: 59.99,
colors: ['Red', 'Green'],
sizes: ['Small', 'Medium', 'Large'],
photos: [
{ height: 100, width: 200, url: '1.jpg' },
{ height: 100, width: 200, url: '2.jpg' },
],
},
update: {
photos: {
push: { height: 300, width: 400, url: '3.jpg' },
},
},
})

删除包含 deletedeleteMany 复合类型的记录

¥Deleting records that contain composite types with delete and deleteMany

要删除嵌入复合类型的记录,请使用 deletedeleteMany 方法。这也将删除嵌入的复合类型。

¥To remove records which embed a composite type, use the delete or deleteMany methods. This will also remove the embedded composite type.

例如,使用 deleteMany 删除所有 size"Small" 的产品。这也将删除任何嵌入的 photos

¥For example, use deleteMany to delete all products with a size of "Small". This will also delete any embedded photos.

const deleteProduct = await prisma.product.deleteMany({
where: {
sizes: {
equals: 'Small',
},
},
})

你还可以使用 filters 删除与复合类型匹配的记录。下面的示例使用 some 过滤器删除包含特定照片的产品:

¥You can also use filters to delete records that match a composite type. The example below uses the some filter to delete products that contain a certain photo:

const product = await prisma.product.deleteMany({
where: {
photos: {
some: {
url: '2.jpg',
},
},
},
})

排序复合类型

¥Ordering composite types

你可以使用 orderBy 操作对结果进行升序或降序排序。

¥You can use the orderBy operation to sort results in ascending or descending order.

例如,以下命令查找所有订单,并按送货地址中的城市名称升序对它们进行排序:

¥For example, the following command finds all orders and orders them by the city name in the shipping address, in ascending order:

const orders = await prisma.order.findMany({
orderBy: {
shippingAddress: {
city: 'asc',
},
},
})

复合类型的唯一字段中的重复值

¥Duplicate values in unique fields of composite types

对具有唯一约束的复合类型的记录执行以下任何操作时请务必小心。在这种情况下,MongoDB 不会强制记录内的值唯一。

¥Be careful when you carry out any of the following operations on a record with a composite type that has a unique constraint. In this situation, MongoDB does not enforce unique values inside a record.

  • 当你创建记录时

    ¥When you create the record

  • 当你向记录添加数据时

    ¥When you add data to the record

  • 当你更新记录中的数据时

    ¥When you update data in the record

如果你的架构具有带有 @@unique 约束的复合类型,MongoDB 会阻止你在包含此复合类型的两个或多个记录中存储相同的约束值。但是,MongoDB 并不阻止你在单个记录中存储同一字段值的多个副本。

¥If your schema has a composite type with a @@unique constraint, MongoDB prevents you from storing the same value for the constrained value in two or more of the records that contain this composite type. However, MongoDB does does not prevent you from storing multiple copies of the same field value in a single record.

请注意,你可以 使用 Prisma ORM 关系来解决此问题

¥Note that you can use Prisma ORM relations to work around this issue.

例如,在以下架构中,MailBox 具有复合类型 addresses,该类型对 email 字段具有 @@unique 约束。

¥For example, in the following schema, MailBox has a composite type, addresses, which has a @@unique constraint on the email field.

type Address {
email String
}

model MailBox {
name String
addresses Address[]

@@unique([addresses.email])
}

以下代码在 address 中创建一条具有两个相同值的记录。MongoDB 在这种情况下不会抛出错误,它会将 alice@prisma.io 存储在 addresses 中两次。

¥The following code creates a record with two identical values in address. MongoDB does not throw an error in this situation, and it stores alice@prisma.io in addresses twice.

await prisma.MailBox.createMany({
data: [
{
name: 'Alice',
addresses: {
set: [
{
address: 'alice@prisma.io', // Not unique
},
{
address: 'alice@prisma.io', // Not unique
},
],
},
},
],
})

注意:如果你尝试在两个单独的记录中存储相同的值,MongoDB 会抛出错误。在上面的示例中,如果你尝试存储用户 Alice 和用户 Bob 的电子邮件地址 alice@prisma.io,MongoDB 不会存储数据并引发错误。

¥Note: MongoDB throws an error if you try to store the same value in two separate records. In our example above, if you try to store the email address alice@prisma.io for the user Alice and for the user Bob, MongoDB does not store the data and throws an error.

使用 Prisma ORM 关系强制记录中的唯一值

¥Use Prisma ORM relations to enforce unique values in a record

在上面的示例中,MongoDB 没有对嵌套地址名称强制执行唯一约束。但是,你可以对数据进行不同的建模,以在记录中强制使用唯一值。为此,请使用 Prisma ORM relations 将复合类型转换为集合。设置与该集合的关系,并对你想要唯一的字段设置唯一约束。

¥In the example above, MongoDB did not enforce the unique constraint on a nested address name. However, you can model your data differently to enforce unique values in a record. To do so, use Prisma ORM relations to turn the composite type into a collection. Set a relationship to this collection and place a unique constraint on the field that you want to be unique.

在以下示例中,MongoDB 在记录中强制执行唯一值。MailboxAddress 型号之间存在关系。此外,Address 模型中的 name 字段具有唯一约束。

¥In the following example, MongoDB enforces unique values in a record. There is a relation between Mailbox and the Address model. Also, the name field in the Address model has a unique constraint.

model Address {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String
mailbox Mailbox? @relation(fields: [mailboxId], references: [id])
mailboxId String? @db.ObjectId

@@unique([name])
}

model Mailbox {
id String @id @default(auto()) @map("_id") @db.ObjectId
name String
addresses Address[] @relation
}
await prisma.MailBox.create({
data: {
name: 'Alice',
addresses: {
create: [
{ name: 'alice@prisma.io' }, // Not unique
{ name: 'alice@prisma.io' }, // Not unique
],
},
},
})

如果运行上面的代码,MongoDB 会强制执行唯一约束。它不允许你的应用添加两个名为 alice@prisma.io 的地址。

¥If you run the above code, MongoDB enforces the unique constraint. It does not allow your application to add two addresses with the name alice@prisma.io.