服務(wù)配置:數(shù)據(jù)建模(SDL)

本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列。

概述

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í)的一些重要概念:

  • TweetUserLocation這三種類型映射到數(shù)據(jù)庫(kù)中的表(table)稽鞭。
  • User和Tweet之間存在雙向關(guān)系
  • TweetLocation之間存在單向關(guān)系
  • User上的name字段外鸟整,數(shù)據(jù)模型中所有字段都是必須的(如類型后面的!所示)
  • idcreatedAtupdatedAt字段由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贷腕,MutationSubscription根類型的實(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嚎朽,MutationSubscription根類型),它定義暴露給客戶端應(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撬码、textisPublished(默認(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)

布爾量其值truefalse金句。

如: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义黎,WIDECOVER的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類型的email字段沽损,其中假設(shè)每個(gè)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è)字段idcreatedAtupdatedAt都有特殊的含義。 它們?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酿箭,createdAtupdatedAt的自定義字段,因?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
}

createdAtupdatedAt

數(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蛉迹。因此用戶地址的字段將是AddressAddress!類型。

包含必需的一對(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)行注釋瞬浓。

這里我們定義了UserStory類型之間的雙向一對(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á)UserStory之間的“作者關(guān)系”腋寨,而且你還需要一個(gè)關(guān)系來(lái)表達(dá)一個(gè)用戶喜歡哪個(gè)故事節(jié)點(diǎn)。

在這種情況下化焕,UserStory之間會(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)與authorlikedBy字段相關(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)將被刪除佃延。
  • 當(dāng)Blog節(jié)點(diǎn)被刪除
    • 所有相關(guān)的Comment節(jié)點(diǎn)將被刪除。
    • 相關(guān)的User節(jié)點(diǎn)將其Blog字段設(shè)置為null夷磕。
  • 當(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)系生成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, 字段名稱為userposts`
  • Appointments , EmployeeOnAppointment , AppointmentEmployee , 字段名稱為 employeeappointments

枚舉

枚舉值只能包含字母、數(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文檔

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末早直,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子市框,更是在濱河造成了極大的恐慌霞扬,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件枫振,死亡現(xiàn)場(chǎng)離奇詭異喻圃,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)粪滤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門斧拍,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人杖小,你說(shuō)我怎么就攤上這事肆汹。” “怎么了予权?”我有些...
    開(kāi)封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵昂勉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我扫腺,道長(zhǎng)岗照,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮谴返,結(jié)果婚禮上煞肾,老公的妹妹穿的比我還像新娘。我一直安慰自己嗓袱,他們只是感情好籍救,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著渠抹,像睡著了一般蝙昙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上梧却,一...
    開(kāi)封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天奇颠,我揣著相機(jī)與錄音,去河邊找鬼放航。 笑死烈拒,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的广鳍。 我是一名探鬼主播荆几,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼赊时!你這毒婦竟也來(lái)了吨铸?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤祖秒,失蹤者是張志新(化名)和其女友劉穎诞吱,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體竭缝,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡房维,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了抬纸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咙俩。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖松却,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情溅话,我是刑警寧澤晓锻,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站飞几,受9級(jí)特大地震影響砚哆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜屑墨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一躁锁、第九天 我趴在偏房一處隱蔽的房頂上張望纷铣。 院中可真熱鬧,春花似錦战转、人聲如沸搜立。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)啄踊。三九已至,卻和暖如春刁标,著一層夾襖步出監(jiān)牢的瞬間颠通,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工膀懈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留顿锰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓启搂,卻偏偏與公主長(zhǎng)得像硼控,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狐血,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列淀歇。 應(yīng)用層和數(shù)據(jù)庫(kù)層分離 兩個(gè)GraphQL API層 在使用Pr...
    guog閱讀 1,144評(píng)論 3 0
  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列。 當(dāng)搞定了GraphQL服務(wù)端開(kāi)發(fā)匈织,且經(jīng)過(guò)充分測(cè)試浪默,那么接著需要...
    guog閱讀 2,627評(píng)論 0 1
  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列。 概述 服務(wù)定義文件prisma.yml具有以下根屬性: dat...
    guog閱讀 2,379評(píng)論 0 0
  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列缀匕。 本教程學(xué)習(xí)如何使用Prisma對(duì)數(shù)據(jù)庫(kù)生成GraphQL AP...
    guog閱讀 7,228評(píng)論 2 3
  • 本文屬使用Prisma構(gòu)建GraphQL服務(wù)系列纳决。 本文介紹如何使用typescript開(kāi)發(fā)prisma服務(wù)。將使...
    guog閱讀 2,891評(píng)論 0 2