概述
Prisma使用GraphQL Schema Definition Language(SDL)進(jìn)行數(shù)據(jù)建模友酱。您的數(shù)據(jù)模型是用一個(gè)或多個(gè).graphql
文件編寫的宪卿,并且是Prisma在底層生成的實(shí)際數(shù)據(jù)庫(kù)schema的基礎(chǔ)史煎。如果您使用單個(gè)文件來(lái)進(jìn)行類型定義互订,則該文件通常稱為datamodel.graphql
。
要了解有關(guān)SDL的更多信息驹马,可以查看官方GraphQL文檔。
包含數(shù)據(jù)模型的.graphql
文件,需要在prisma.yml
文件中datamodel
屬性下的指定糯累。例如:
datamodel:
- types.graphql
- enums.graphql
如果只有一個(gè)文件定義數(shù)據(jù)模型算利,則可以如下方式指定:
datamodel: datamodel.graphql
數(shù)據(jù)模型是Prisma服務(wù)的GraphQL API的基礎(chǔ)∮窘悖基于數(shù)據(jù)模型效拭,Prisma將生成一個(gè)強(qiáng)大的GraphQL schema(稱為Prisma database schema),該schema為數(shù)據(jù)模型中的類型定義了CRUD操作胖秒。
GraphQL模式定義了GraphQL API的操作缎患。它實(shí)際上是用SDL編寫的類型集合(SDL還支持接口,枚舉扒怖,聯(lián)合類型等基元较锡,您可以在這里了解有關(guān)GraphQL類型系統(tǒng)的內(nèi)容)。 GraphQL schema有三種特殊的根類型:查詢盗痒,突變和訂閱蚂蕴。這些類型定義了API的入口點(diǎn)并定義了API將接受的操作。要了解更多關(guān)于GraphQL schema的信息俯邓,請(qǐng)查看這篇文章骡楼。
示例
一個(gè)簡(jiǎn)單的datamodel.graphql
文件:
type Tweet {
id: ID! @unique
createdAt: DateTime!
text: String!
owner: User!
location: Location!
}
type User {
id: ID! @unique
createdAt: DateTime!
updatedAt: DateTime!
handle: String! @unique
name: String
tweets: [Tweet!]!
}
type Location {
latitude: Float!
longitude: Float!
}
這個(gè)例子展示了使用數(shù)據(jù)模型時(shí)的一些重要概念:
-
Tweet
,User
和Location
這三種類型映射到數(shù)據(jù)庫(kù)中的表(table)稽鞭。 -
User
和Tweet之間存在雙向關(guān)系 -
Tweet
與Location
之間存在單向關(guān)系 - 除
User
上的name
字段外鸟整,數(shù)據(jù)模型中所有字段都是必須的(如類型后面的!
所示) -
id
,createdAt
和updatedAt
字段由Prisma管理朦蕴,在公開(kāi)的GraphQL API中為只讀(意味著它們不能通過(guò)突變進(jìn)行更改)篮条。
創(chuàng)建和更新數(shù)據(jù)模型與編寫文本文件一樣簡(jiǎn)單。對(duì)數(shù)據(jù)模型滿意后吩抓,您可以通過(guò)運(yùn)行prisma deploy
將更改應(yīng)用到Prisma服務(wù):
$ prisma deploy
Changes:
Tweet (Type)
+ Created type `Tweet`
+ Created field `id` of type `GraphQLID!`
+ Created field `createdAt` of type `DateTime!`
+ Created field `text` of type `String!`
+ Created field `owner` of type `Relation!`
+ Created field `location` of type `Relation!`
+ Created field `updatedAt` of type `DateTime!`
User (Type)
+ Created type `User`
+ Created field `id` of type `GraphQLID!`
+ Created field `createdAt` of type `DateTime!`
+ Created field `updatedAt` of type `DateTime!`
+ Created field `handle` of type `String!`
+ Created field `name` of type `String`
+ Created field `tweets` of type `[Relation!]!`
Location (Type)
+ Created type `Location`
+ Created field `latitude` of type `Float!`
+ Created field `longitude` of type `Float!`
+ Created field `id` of type `GraphQLID!`
+ Created field `updatedAt` of type `DateTime!`
+ Created field `createdAt` of type `DateTime!`
TweetToUser (Relation)
+ Created relation between Tweet and User
LocationToTweet (Relation)
+ Created relation between Location and Tweet
Applying changes... (22/22)
Applying changes... 0.4s
數(shù)據(jù)模型的構(gòu)建塊
有幾種可用的構(gòu)建模塊來(lái)構(gòu)造您的數(shù)據(jù)模型:
- 類型由多個(gè)字段組成涉茧,用于將相似的實(shí)體組合在一起。數(shù)據(jù)模型中的每種類型都映射到數(shù)據(jù)庫(kù)疹娶,并將CRUD操作添加到GraphQL schema中伴栓。
- 關(guān)系描述類型之間的關(guān)系。
- 接口是抽象類型雨饺,它包含一組必須包含的用于實(shí)現(xiàn)接口的字段钳垮。目前,接口不能由用戶定義额港,但有高級(jí)接口支持的待定功能請(qǐng)求饺窿。
- 特殊指令涵蓋不同的用例,如類型約束或級(jí)聯(lián)刪除行為锹安。
本頁(yè)面的其余部分將更詳細(xì)地介紹這些構(gòu)建塊短荐。
Prisma database schema 與 Data Model
當(dāng)開(kāi)始使用GraphQL和Prisma時(shí)倚舀,您正在使用的.graphql
文件的數(shù)量可能會(huì)令人困惑。然而忍宋,了解每個(gè)的角色至關(guān)重要痕貌。
通常,.graphql
文件可以包含以下任一項(xiàng):
- GraphQL操作(即查詢糠排,突變或訂閱)
- SDL中的GraphQL類型定義
在區(qū)分Prisma database schema 與 Data Model的前提下舵稠,只有后者才相關(guān)!
請(qǐng)注意入宦,并非每個(gè)后一類別的.graphql
文件都是有效的GraphQL schema哺徊。正如上面的提到的,GraphQL schema的特點(diǎn)是它有三種根類型:查詢乾闰,突變和訂閱以及API所需的任何其他類型落追。
現(xiàn)在,通過(guò)該定義涯肩,數(shù)據(jù)模型實(shí)際上并不是GraphQL schema轿钠,盡管它是用SDL編寫的.graphql
文件。它缺少根類型病苗,因此實(shí)際上并沒(méi)有定義API操作疗垛! Prisma像是使用數(shù)據(jù)模型作為一個(gè)方便的工具來(lái)表示數(shù)據(jù)模型。
如上所述硫朦,Prisma將生成一個(gè)包含Query
贷腕,Mutation
和Subscription
根類型的實(shí)際GraphQL schema。該schema通常作為prisma.graphql
存儲(chǔ)在您的項(xiàng)目中咬展,并稱為Prisma database schema泽裳。請(qǐng)注意,您不應(yīng)該對(duì)此文件進(jìn)行任何手動(dòng)更改破婆!
作為一個(gè)例子诡壁,請(qǐng)考慮以下非常簡(jiǎn)單的數(shù)據(jù)模型:
datamodel.graphql
type User {
id: ID! @uniue
name: String!
}
如果您將此數(shù)據(jù)模型部署到您的Prisma服務(wù)中,Prisma將生成以下Prisma database schema荠割,該schema定義您的服務(wù)的GraphQL API:
prisma.graphql
type Query {
users(where: UserWhereInput, orderBy: UserOrderByInput, skip: Int, after: String, before: String, first: Int, last: Int): [User]!
user(where: UserWhereUniqueInput!): User
}
type Mutation {
createUser(data: UserCreateInput!): User!
updateUser(data: UserUpdateInput!, where: UserWhereUniqueInput!): User
deleteUser(where: UserWhereUniqueInput!): User
}
type Subscription {
user(where: UserSubscriptionWhereInput): UserSubscriptionPayload
}
請(qǐng)注意,這是生成的schema的簡(jiǎn)化版本旺矾,您可以在此處找到完整的schema蔑鹦。
如果您已經(jīng)考慮構(gòu)建基于Prisma的自己的GraphQL服務(wù),則可能會(huì)遇到另一個(gè)被稱為application schema的.graphql文件箕宙。這是另一個(gè)適當(dāng)?shù)腉raphQL schema(意味著它包含Query
嚎朽,Mutation
和Subscription
根類型),它定義暴露給客戶端應(yīng)用程序的API柬帕。它使用底層的Prisma GraphQL API作為“查詢引擎”來(lái)實(shí)際運(yùn)行數(shù)據(jù)庫(kù)的查詢哟忍,變異和訂閱狡门。 基于Prisma的GraphQL服務(wù)通常具有兩個(gè)GraphQL API,將它們視為服務(wù)的兩個(gè)層次:
- 應(yīng)用層:由應(yīng)用模式定義(這里是您實(shí)現(xiàn)業(yè)務(wù)邏輯锅很,認(rèn)證其馏,與第三方服務(wù)集成等的地方)
- 數(shù)據(jù)庫(kù)層:由Prisma數(shù)據(jù)庫(kù)服務(wù)定義
對(duì)象類型(Object types)
對(duì)象類型(簡(jiǎn)稱為類型)定義數(shù)據(jù)模型的一個(gè)具體的結(jié)構(gòu)。它用于表示應(yīng)用程序域(application domain)的實(shí)體爆安。
如果您熟悉SQL數(shù)據(jù)庫(kù)叛复,則可以將對(duì)象類型視為關(guān)系數(shù)據(jù)庫(kù)中的表的schema。一個(gè)類型有一個(gè)名字和一個(gè)或多個(gè)字段扔仓。
一個(gè)類型的實(shí)例被稱為節(jié)點(diǎn)(node)褐奥。這個(gè)術(shù)語(yǔ)是指數(shù)據(jù)圖(data graph)中的一個(gè)節(jié)點(diǎn)。您在數(shù)據(jù)模型中定義的每種類型都將作為生成的Prisma database schema中的類似類型提供翘簇。
定義對(duì)象類型
在數(shù)據(jù)模型中使用type
關(guān)鍵字定義對(duì)象類型:
type Article {
id: ID! @unique
text: String!
isPublished: Boolean @default(value: "false")
}
上面定義的類型具有以下屬性:
- 名稱:
Article
- 字段:
id
撬码、text
和isPublished
(默認(rèn)值為false
)
為類型生成操作API
數(shù)據(jù)模型中的類型會(huì)影響Prisma GraphQL API中的可用操作。對(duì)于每種類型版保,
- query 允許獲取一個(gè)或多個(gè)類型節(jié)點(diǎn)
- mutation 允許創(chuàng)建、修改或刪除類型的節(jié)點(diǎn)
- subscription 允許當(dāng)節(jié)點(diǎn)改變時(shí)獲取通知(例如新節(jié)點(diǎn)添加蹈垢,現(xiàn)有節(jié)點(diǎn)修改或刪除)
字段(Fields)
字段是一種類型的構(gòu)成曹抬,表示節(jié)點(diǎn)的形狀谤民。每個(gè)字段是標(biāo)量或關(guān)系字段疾宏,可以使用其名稱引用坎藐。
標(biāo)量類型
字符串(string)
一個(gè)字符串String
為文本岩馍,用于username
類型蛀恩、博客文章的內(nèi)容或任何適合文本表示的內(nèi)容。
注意:共享演示群集上的字符串值目前限制為256KB壳咕。使用集群(cluster)配置的其他群集可以提高此限制。
在查詢或突變中幌羞,必須使用括住雙引號(hào)(""
)來(lái)指定字符串字段:string:“some-string”
新翎。
整型(nteger)
Int
是一個(gè)不能有小數(shù)的數(shù)字住练。使用它來(lái)存儲(chǔ)值讲逛,例如配方所需的配料重量或最小年齡盏混。
注意:
Int
值范圍從-2147483648到2147483647。
在查詢或突變中止喷,指定Int
字段:int:42
弹谁。
浮點(diǎn)(Float)
浮點(diǎn)數(shù)(Float)是可以有小數(shù)的數(shù)字句喜。使用它可以存儲(chǔ)諸如商店中商品價(jià)格或復(fù)雜計(jì)算結(jié)果等值咳胃。
在查詢或突變中,指定Float字段:float:42销睁,float:4.2
存崖。
布爾量(Boolean)
布爾量其值true
或false
金句。
如:boolean: true, boolean: false
日期時(shí)間(DateTime)
DateTime
類型可用于存儲(chǔ)日期或時(shí)間值违寞。一個(gè)很好的例子可能是一個(gè)人的出生日期。
在查詢或突變中军浆,必須用ISO 8601格式指定DateTime字段并加上雙引號(hào):
datetime: "2015"
datetime: "2015-11"
datetime: "2015-11-22"
datetime: "2015-11-22T13:57:31.123Z"
枚舉(Enum)
枚舉被定義在范圍內(nèi)乒融。
像布爾值一樣赞季,枚舉可以有一組預(yù)定義的值奢驯。區(qū)別在于您可以定義可能的值瘪阁。例如,您可以通過(guò)創(chuàng)建具有可能值COMPACT
义黎,WIDE
和COVER
的Enum來(lái)指定文章的格式廉涕。
注意:枚舉值最多可以有191個(gè)字符長(zhǎng)贩绕。
在查詢或突變中淑倾,必須指定Enum字段馏鹤,而不使用任何包圍字符湃累。您只能使用您為枚舉定義的值:enum:COMPACT
治力,enum:WIDE
勃黍。
JSON
有時(shí)您需要為松散結(jié)構(gòu)化的數(shù)據(jù)存儲(chǔ)任意的Json值覆获。 Json類型確保它實(shí)際上是有效的Json瓢省,并將該值作為解析的Json對(duì)象/數(shù)組而不是字符串返回痊班。
注意:共享演示群集上的Json值目前限制為256KB涤伐。使用集群配置(cluster configuration)的其他群集可以提高此限制凝果。
在查詢或突變中,Json字段必須用雙引號(hào)括起來(lái)液兽。特殊字符必須轉(zhuǎn)義:json: "{\"int\": 1, \"string\": \"value\"}"
。
ID
ID值是基于cuid生成的唯一的25個(gè)字符的字符串粗恢。具有ID值的字段是系統(tǒng)字段眷射,只是在內(nèi)部使用妖碉,因此無(wú)法使用ID類型創(chuàng)建新字段坐榆。
類型修飾符
列表(List)
標(biāo)量字段可以用列表字段類型標(biāo)記席镀。具有多重性的關(guān)系的字段也將被標(biāo)記為列表豪诲。
在查詢或突變中屎篱,列表字段必須用方括號(hào)([]
)括起來(lái)芳室,而列表中的每項(xiàng)遵守與上面標(biāo)量列出的相同的格式化規(guī)則:listString: ["a string", "another string"], listInt: [12, 24]
必須(Required)
必須字段(有時(shí)也稱為“非空”)荔仁。在創(chuàng)建新節(jié)點(diǎn)時(shí),您需要為所需字段提供一個(gè)值,并且沒(méi)有默認(rèn)值。
必填字段在字段類型后使用!
標(biāo)記:name:String!
.
字段約束
可以使用特定的字段約束來(lái)配置字段,以便將更多語(yǔ)義添加到數(shù)據(jù)模型中。
唯一(Unique)
設(shè)置unique
可確保相關(guān)類型的兩個(gè)節(jié)點(diǎn)對(duì)于某個(gè)字段的值不能重復(fù)。唯一的例外是null
,這意味著多個(gè)節(jié)點(diǎn)可以具有null
值而不違反約束。
典型的例子是
User
類型的user
都有唯一的電子郵件地址炎疆。
注意,只有字符串字段中的前191個(gè)字符才被認(rèn)為是唯一性的蛇数,并且唯一性檢查是不區(qū)分大小寫的碌上。 如果前191個(gè)字符相同或僅大小寫不同辑畦,則不能存儲(chǔ)兩個(gè)不同的字符串。
要將某個(gè)字段標(biāo)記為唯一,只需將@unique
添加到其后面:
type User {
email: String! @unique
age: Int!
}
對(duì)于每個(gè)使用@unique
標(biāo)記的字段,您都可以通過(guò)為該字段提供一個(gè)值來(lái)查詢相應(yīng)的節(jié)點(diǎn)。
例如,對(duì)于上述數(shù)據(jù)模型妖混,您現(xiàn)在可以通過(guò)其電子郵件地址檢索特定的用戶節(jié)點(diǎn):
query {
user(where: {
email: "alice@graph.cool"
}) {
age
}
}
默認(rèn)值
您可以為標(biāo)量字段設(shè)置默認(rèn)值祥楣。在創(chuàng)建期間未提供值時(shí),將為新節(jié)點(diǎn)采用該值薇搁。
要為字段指定默認(rèn)值传货,可以使用@default
指令:
type Story {
isPublished: Boolean @default(value: "false")
someNumber: Int! @default(value: "42")
title: String! @default(value: "My New Post")
publishDate: DateTime! @default(value: "2018-01-26")
}
請(qǐng)注意,必須使用雙引號(hào)提供默認(rèn)值,即使對(duì)于非字符串類型(例如Boolean或Int)也是如此扛伍。
系統(tǒng)字段
三個(gè)字段id
,createdAt
和updatedAt
都有特殊的含義。 它們?cè)谀臄?shù)據(jù)模型中是可選的栏饮,但將始終保留在底層數(shù)據(jù)庫(kù)中逢享。 這樣矢空,您可以隨后將字段添加到數(shù)據(jù)模型中屁药,并且數(shù)據(jù)將可用于現(xiàn)有節(jié)點(diǎn)。
這些字段的值目前在GraphQL API中是只讀的(除了導(dǎo)入數(shù)據(jù)時(shí)).
請(qǐng)注意柏锄,您不能擁有稱為id
酿箭,createdAt
和updatedAt
的自定義字段,因?yàn)檫@些字段名稱是為系統(tǒng)字段保留的绢彤。以下是這三個(gè)字段唯一支持的聲明:
id: ID! @unique
createdAt: DateTime!
updatedAt: DateTime!
id
節(jié)點(diǎn)在創(chuàng)建時(shí)會(huì)自動(dòng)獲取全局唯一標(biāo)識(shí)符七问,該標(biāo)識(shí)符存儲(chǔ)在id
字段中。
無(wú)論何時(shí)將id
字段添加到類型定義以將其暴露在GraphQL API中茫舶,您都必須使用@unique
指令對(duì)其進(jìn)行標(biāo)記械巡。
該id
具有以下屬性:
- 由25個(gè)字母數(shù)字字符組成(字母總是小寫)
- 始終以(小寫)字母c開(kāi)頭
- 遵循 cuid(collision resistant unique identifiers)方案
請(qǐng)注意,所有對(duì)象類型都將在數(shù)據(jù)庫(kù)模式中實(shí)現(xiàn)Node
接口饶氏。這就是Node
接口的樣子:
interface Node {
id: ID! @unique
}
createdAt
和updatedAt
數(shù)據(jù)模型還提供了兩個(gè)可以添加到類型中的特殊字段:
-
createdAt:DateTime !
存儲(chǔ)創(chuàng)建此對(duì)象類型的節(jié)點(diǎn)時(shí)的實(shí)際日期和時(shí)間讥耗。 -
updatedAt: DateTime!
存儲(chǔ)上次更新此對(duì)象類型的節(jié)點(diǎn)時(shí)的確切日期和時(shí)間。
如果你想讓你的類型公開(kāi)這些字段疹启,你可以簡(jiǎn)單地將它們添加到類型定義中古程,例如:
type User {
id: ID! @unique
createdAt: DateTime!
updatedAt: DateTime!
}
標(biāo)量字段值遷移
您可以使用updateManyXs
突變?yōu)樗泄?jié)點(diǎn)或僅特定子集遷移標(biāo)量字段的值。
mutation {
# update the email of all users with no email address to the empty string
updateManyUsers(
where: {
email: null
}
data: {
email: ""
}
)
}
向數(shù)據(jù)模型添加一個(gè)必填字段
將必需的字段添加到已包含節(jié)點(diǎn)的模型時(shí)喊崖,您會(huì)收到此錯(cuò)誤消息:
You are making a field required, but there are already nodes that would violate that constraint.您正在創(chuàng)建一個(gè)必需的字段挣磨,但已有節(jié)點(diǎn)會(huì)違反該限制雇逞。
這是因?yàn)樗泄?jié)點(diǎn)對(duì)于這個(gè)字段都是空的。
以下是添加必填字段所需的步驟:
- 添加可選(
optional
)的字段茁裙。 - 使用
updateManyXs
將字段的所有節(jié)點(diǎn)從null
變?yōu)橐粋€(gè)非空值塘砸。 - 現(xiàn)在您可以根據(jù)需要標(biāo)記該字段并部署
關(guān)系
關(guān)系定義了兩種類型之間連接的語(yǔ)義。 關(guān)系中的兩種類型通過(guò)關(guān)系字段連接晤锥。 當(dāng)關(guān)系可能不明確時(shí)掉蔬,關(guān)系字段需要用@relation
指令注釋以消除它的歧義。
一個(gè)關(guān)系也可以將一個(gè)類型與自己連接起來(lái)——稱為自我關(guān)系矾瘾。
所需的關(guān)系
對(duì)于一對(duì)一關(guān)系字段女轿,您可以配置它是必需的還是可選的。所需的標(biāo)志在GraphQL中充當(dāng)契約壕翩,該字段不能為null
蛉迹。因此用戶地址的字段將是Address
或Address!
類型。
包含必需的一對(duì)一關(guān)系字段的類型的節(jié)點(diǎn)只能使用嵌套突變(nested mutation)放妈,以確保相關(guān)字段不會(huì)為null
婿禽。
請(qǐng)注意,多對(duì)多關(guān)系字段始終設(shè)置為必需大猛。例如,包含許多用戶地址的字段總是使用類型
[Address!]!
并且不能是[Address!]
類型淀零。原因是挽绩,如果該字段不包含任何節(jié)點(diǎn),將返回[]
驾中,該值不為null
唉堪。
@relation 指令
定義類型之間的關(guān)系時(shí),有@relation
指令提供關(guān)于關(guān)系的元信息肩民。它可以有兩個(gè)參數(shù):
-
name
: 此關(guān)系的標(biāo)識(shí)符(以字符串形式提供)唠亚。這個(gè)論點(diǎn)只有在關(guān)系不明確的情況下才需要。請(qǐng)注意持痰,每次使用@relation
指令時(shí)灶搜,name
參數(shù)都是必需的。 -
onDelete
: 指定刪除行為并啟用級(jí)聯(lián)刪除工窍。如果具有相關(guān)節(jié)點(diǎn)的節(jié)點(diǎn)被刪除割卖,則刪除行為決定了相關(guān)節(jié)點(diǎn)應(yīng)該發(fā)生什么。該參數(shù)的輸入值被定義為具有以下可能值的枚舉:-
SET_NULL
(默認(rèn)):將相關(guān)節(jié)點(diǎn)設(shè)置為null
患雏。 -
CASCADE
:刪除相關(guān)的節(jié)點(diǎn)鹏溯。請(qǐng)注意,無(wú)法將雙向關(guān)系的兩端設(shè)置為CASCADE
淹仑。
-
以下是使用@relation
指令的數(shù)據(jù)模型示例:
type User {
id: ID! @unique
stories: [Story!]! @relation(name: "StoriesByUser" onDelete: CASCADE)
}
type Story {
id: ID! @unique
text: String!
author: User @relation(name: "StoriesByUser")
}
本例中的刪除行為如下所示:
- 當(dāng)用戶節(jié)點(diǎn)被刪除時(shí)丙挽,其所有相關(guān)的
Story
節(jié)點(diǎn)也將被刪除肺孵。 - 當(dāng)
Story
節(jié)點(diǎn)被刪除時(shí),它將被簡(jiǎn)單地從相關(guān)User
節(jié)點(diǎn)上的Story
列表中刪除颜阐。
省略@relation
指令
在最簡(jiǎn)單的情況下平窘,如果兩種類型之間的關(guān)系是明確的并且應(yīng)該應(yīng)用缺省刪除行為(SET_NULL
),則相應(yīng)的關(guān)系字段不必使用@relation
指令進(jìn)行注釋瞬浓。
這里我們定義了User
和Story
類型之間的雙向一對(duì)多關(guān)系初婆。由于沒(méi)有提供onDelete
,所以使用了SET_NULL
默認(rèn)的刪除行為:
type User {
id: ID! @unique
stories: [Story!]!
}
type Story {
id: ID! @unique
text: String!
author: User
}
刪除行為如下:
- 當(dāng)用戶節(jié)點(diǎn)被刪除時(shí)猿棉,其所有相關(guān)
Story
節(jié)點(diǎn)上的author
字段將被設(shè)置為null
磅叛。請(qǐng)注意,如果author
字段被標(biāo)記為必需萨赁,則操作會(huì)導(dǎo)致錯(cuò)誤弊琴。 - 當(dāng)
Story
節(jié)點(diǎn)被刪除時(shí),它將被簡(jiǎn)單地從相關(guān)User
節(jié)點(diǎn)上的Story
列表中刪除杖爽。
使用@relation
指令的name
參數(shù)
在某些情況下敲董,您的數(shù)據(jù)模型可能包含不明確的關(guān)系。例如慰安,考慮你不僅想要一個(gè)關(guān)系來(lái)表達(dá)User
和Story
之間的“作者關(guān)系”腋寨,而且你還需要一個(gè)關(guān)系來(lái)表達(dá)一個(gè)用戶喜歡哪個(gè)故事節(jié)點(diǎn)。
在這種情況下化焕,User
和Story
之間會(huì)有兩種不同的關(guān)系萄窜!為了消除它們的歧義,你需要給關(guān)系一個(gè)名字:
type User {
id: ID! @unique
writtenStories: [Story!]! @relation(name: "WrittenStories")
likedStories: [Story!]! @relation(name: "LikedStories")
}
type Story {
id: ID! @unique
text: String!
author: User! @relation(name: "WrittenStories")
likedBy: [User!]! @relation(name: "LikedStories")
}
如果在這種情況下未提供name
參數(shù)撒桨,則無(wú)法確定書寫的作品是否應(yīng)與author
或likedBy
字段相關(guān)聯(lián)查刻。
使用@relation
指令的onDelete
參數(shù)
如上所述,您可以為相關(guān)節(jié)點(diǎn)指定專門的刪除行為凤类。這就是@relation
指令的onDelete
參數(shù)所要做的穗泵。
考慮下面的例子:
type User {
id: ID! @unique
comments: [Comment!]! @relation(name: "CommentAuthor", onDelete: CASCADE)
blog: Blog @relation(name: "BlogOwner", onDelete: CASCADE)
}
type Blog {
id: ID! @unique
comments: [Comment!]! @relation(name: "Comments", onDelete: CASCADE)
owner: User! @relation(name: "BlogOwner", onDelete: SET_NULL)
}
type Comment {
id: ID! @unique
blog: Blog! @relation(name: "Comments", onDelete: SET_NULL)
author: User @relation(name: "CommentAuthor", onDelete: SET_NULL)
}
我們來(lái)研究這三種類型的刪除行為:
- 當(dāng)
User
節(jié)點(diǎn)被刪除時(shí),- 所有相關(guān)的
Comment
節(jié)點(diǎn)將被刪除谜疤。 - 相關(guān)的
Blog
節(jié)點(diǎn)將被刪除佃延。
- 所有相關(guān)的
- 當(dāng)
Blog
節(jié)點(diǎn)被刪除- 所有相關(guān)的
Comment
節(jié)點(diǎn)將被刪除。 - 相關(guān)的
User
節(jié)點(diǎn)將其Blog
字段設(shè)置為null
夷磕。
- 所有相關(guān)的
- 當(dāng)
Comment
節(jié)點(diǎn)被刪除時(shí)苇侵,- 相關(guān)的
Blog
節(jié)點(diǎn)將繼續(xù)存在,并將刪除的Comment
節(jié)點(diǎn)從其comments
列表中刪除企锌。 - 他相關(guān)
User
節(jié)點(diǎn)將繼續(xù)存在榆浓,并將刪除的Comment
節(jié)點(diǎn)從其comments
列表中刪除。
- 相關(guān)的
為關(guān)系生成API操作
包含在您的schema
中的關(guān)系會(huì)影響GraphQL API中的可用操作撕攒。對(duì)于每一個(gè)關(guān)系陡鹃,
- 關(guān)系查詢(relation queries)允許您跨類型查詢數(shù)據(jù)或?yàn)殛P(guān)系聚合(請(qǐng)注意烘浦,使用Relay的連接模型connection model也可以)
- 嵌套突變(nested mutations)允許您創(chuàng)建,連接萍鲸,更新闷叉,插入和刪除不同類型的節(jié)點(diǎn)
- 關(guān)系訂閱(relation subscriptions)允許您獲得有關(guān)關(guān)系更改的通知
GraphQL指令
指令用于在數(shù)據(jù)模型中提供附加信息。它們看起來(lái)像這樣:@name(argument: "value")
或者當(dāng)沒(méi)有參數(shù)時(shí)只是@name
脊阴。
數(shù)據(jù)模型指令
數(shù)據(jù)模型指令描述了關(guān)于GraphQL schema中的類型或字段的附加信息握侧。
唯一標(biāo)量字段
@unique
指令將標(biāo)量字段標(biāo)記為唯一(unique)。唯一字段將在底層數(shù)據(jù)庫(kù)中應(yīng)用唯一索引嘿期。
# the `User` type has a unique `email` field
type User {
email: String @unique
}
關(guān)系字段
可以將指令@relation(name:String品擎,onDelete:ON_DELETE!=NO_ACTION)
附加到關(guān)系字段。
標(biāo)量字段的默認(rèn)值
指令@default(value: String!)
為標(biāo)量字段設(shè)置默認(rèn)值备徐。請(qǐng)注意萄传,value
參數(shù)對(duì)于所有標(biāo)量字段都是String
類型(即使字段本身不是字符串):
# the `title`, `published` and `someNumber` fields have default values `New Post`, `false` and `42`
type Post {
title: String! @default(value: "New Post")
published: Boolean! @default(value: "false")
someNumber: Int! @default(value: "42")
}
臨時(shí)指令
臨時(shí)指令用于執(zhí)行一次性遷移操作。部署包含臨時(shí)指令的服務(wù)后蜜猾,需要從類型定義文件中手動(dòng)刪除它秀菱。
重命名類型或字段
臨時(shí)指令@rename(oldName: String!)
用于重命名類型或字段宅粥。
# renaming the `Post` type to `Story`, and its `text` field to `content`
type Story @rename(oldName: "Post") {
content: String @rename(oldName: "text")
}
如果沒(méi)有使用rename指令分歇,Prisma會(huì)在創(chuàng)建新類型和字段之前刪除舊類型和字段,導(dǎo)致數(shù)據(jù)丟失懦胞!
命名約定
您在Prisma服務(wù)中遇到的不同對(duì)象(如類型或關(guān)系)遵循單獨(dú)的命名約定來(lái)幫助區(qū)分它們肩豁。
類型
類型名稱決定派生查詢和變異的名稱以及嵌套變異的參數(shù)名稱梦碗。類型名稱只能包含字母和數(shù)字,并且需要以大寫字母開(kāi)頭蓖救。它們最多64個(gè)字符。
建議以單數(shù)形式選擇類型名稱印屁。
類型名稱在服務(wù)級(jí)別上是唯一的循捺。
示例:
Post
PostCategory
標(biāo)量和關(guān)系字段
標(biāo)量字段的名稱用于查詢和突變的查詢參數(shù)中。字段名稱只能包含字母和數(shù)字雄人,并且需要以小寫字母開(kāi)頭从橘。它們最多可以包含64個(gè)字符。
關(guān)系字段的名稱遵循相同的約定础钠,并確定關(guān)系突變的參數(shù)名稱恰力。
建議只為列表字段選擇復(fù)數(shù)名稱。
字段名稱在類型級(jí)別上是唯一的旗吁。
示例:
name
email
categoryTags
關(guān)系
關(guān)系名稱只能包含字母和數(shù)字,并且需要以大寫字母開(kāi)頭很钓。它們最多可以包含64個(gè)字符香府。 關(guān)系名稱在服務(wù)級(jí)別上是唯一的董栽。
示例:
-
UserOnPost
,UserPosts
,PostAuthor, 字段名稱為
user和
posts` -
Appointments
,EmployeeOnAppointment
,AppointmentEmployee
, 字段名稱為employee
和appointments
枚舉
枚舉值只能包含字母、數(shù)字和下劃線企孩,并且需要以大寫字母開(kāi)頭锭碳。枚舉值的名稱可以用于查詢過(guò)濾器和突變。它們最多可以包含191個(gè)字符勿璃。
枚舉名稱在服務(wù)級(jí)別上是唯一的擒抛。
枚舉值名稱在枚舉級(jí)別上是唯一的。
示例
A
ROLE_TAG
RoleTag
更多SDL功能
在本節(jié)中补疑,我們將介紹尚未支持用Prisma進(jìn)行數(shù)據(jù)建模的更多SDL功能歧沪。
接口
“與許多類型的系統(tǒng)一樣,GraphQL支持接口癣丧。接口是一種抽象類型槽畔,包含一組必須包含的用于實(shí)現(xiàn)接口的字段⌒脖啵”——官方GraphQL文檔
Union
“聯(lián)合類型與接口非常相似厢钧,但它們不能指定類型之間的任何公共字段℃页龋”——官方GraphQL文檔