跳到主要內容

資料建模

什麼是資料建模?

術語 資料建模 是指定義應用程式中物件的形狀和結構的過程,這些物件通常被稱為“應用程式模型”。在關係型資料庫(如 PostgreSQL)中,它們儲存在 中。在使用文件型資料庫(如 MongoDB)時,它們儲存在 集合 中。

根據你應用程式的領域,模型會有所不同。例如,如果你正在編寫一個部落格應用程式,你可能會有 部落格作者文章 等模型。在編寫拼車應用程式時,你可能會有 司機汽車路線 等模型。應用程式模型使你能夠透過建立相應的資料結構在程式碼中表示這些不同的實體。

在資料建模時,你通常會問以下問題:

  • 我應用程式中的主要實體/概念是什麼?
  • 它們之間如何關聯?
  • 它們的主要特徵/屬性是什麼?
  • 如何使用我的技術棧來表示它們?

不使用 Prisma ORM 的資料建模

資料建模通常需要在(至少)兩個層面進行:

  • 資料庫層面
  • 應用程式層面(即,在你的程式語言中)

應用程式模型在這兩個層面上的表示方式可能因以下幾個原因而不同:

  • 資料庫和程式語言使用不同的資料型別
  • 關係在資料庫中的表示方式與在程式語言中的表示方式不同
  • 資料庫通常具有更強大的資料建模能力,例如索引、級聯刪除或各種附加約束(例如唯一、非空等)
  • 資料庫和程式語言有不同的技術約束

資料庫層面的資料建模

關係型資料庫

在關係型資料庫中,模型由 表示。例如,你可以定義一個 users 表來儲存應用程式的使用者資訊。使用 PostgreSQL,你可以按如下方式定義它:

CREATE TABLE users (
user_id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(255),
email VARCHAR(255) UNIQUE NOT NULL,
isAdmin BOOLEAN NOT NULL DEFAULT false
);

包含一些隨機資料的 users 表的視覺化表示可能如下所示:

user_idnameemailisAdmin
1Alicealice@prisma.iofalse
2Bobbob@prisma.iofalse
3Sarahsarah@prisma.iotrue

它包含以下列:

  • user_id:一個整數,users 表中每條新記錄都會遞增。它還表示每條記錄的主鍵
  • name:一個最多包含 255 個字元的字串。
  • email:一個最多包含 255 個字元的字串。此外,新增的約束表示 email 列不允許存在重複值,並且每條記錄都必須為其設定值。
  • isAdmin:一個布林值,指示使用者是否具有管理員許可權(預設值:false

MongoDB

在 MongoDB 資料庫中,模型由 集合 表示,幷包含可以具有任何結構的 文件

{
_id: '607ee94800bbe41f001fd568',
slug: 'prisma-loves-mongodb',
title: 'Prisma <3 MongoDB',
body: "This is my first post. Isn't MongoDB + Prisma awesome?!"
}

Prisma Client 當前期望一致的模型和 規範化模型設計。這意味著:

  • 如果模型或欄位不在 Prisma schema 中,它將被忽略
  • 如果一個欄位是必填的但在 MongoDB 資料集中不存在,你將收到一個錯誤

應用程式層面的資料建模

除了建立表示應用程式領域中實體的表之外,你還需要在程式語言中建立應用程式模型。在面嚮物件語言中,這通常透過建立 來表示你的模型。根據程式語言的不同,這也可以透過 介面結構體 來完成。

資料庫中的表與程式碼中定義的模型之間通常存在很強的關聯性。例如,要在應用程式中表示上述 users 表中的記錄,你可能會定義一個類似於這樣的 JavaScript (ES6) 類:

class User {
constructor(user_id, name, email, isAdmin) {
this.user_id = user_id
this.name = name
this.email = email
this.isAdmin = isAdmin
}
}

使用 TypeScript 時,你可能會定義一個介面來代替:

interface User {
user_id: number
name: string
email: string
isAdmin: boolean
}

請注意,在兩種情況下,User 模型都具有與前一個示例中 users 表相同的屬性。雖然資料庫表和應用程式模型之間通常存在 1:1 的對映關係,但也可能出現模型在資料庫和應用程式中表示方式完全不同的情況。

透過此設定,你可以從 users 表中檢索記錄,並將其儲存為 User 型別的例項。以下示例程式碼片段使用 pg 作為 PostgreSQL 驅動,並根據上面定義的 JavaScript 類建立了一個 User 例項:

const resultRows = await client.query('SELECT * FROM users WHERE user_id = 1')
const userData = resultRows[0]
const user = new User(
userData.user_id,
userData.name,
userData.email,
userData.isAdmin
)
// user = {
// user_id: 1,
// name: "Alice",
// email: "alice@prisma.io",
// isAdmin: false
// }

請注意,在這些示例中,應用程式模型是“啞”的,這意味著它們不實現任何邏輯,其唯一目的是以 *普通 JavaScript 物件* 的形式攜帶資料。

使用 ORM 進行資料建模

ORM 通常用於面嚮物件語言,以方便開發者使用資料庫。ORM 的關鍵特性是它允許你以 *類* 的形式對應用程式資料進行建模,這些類被對映到底層資料庫中的 *表*。

與上述方法相比,主要區別在於這些類不僅承載資料,還實現了大量的邏輯。主要用於儲存、檢索、序列化和反序列化,但有時它們也會實現特定於你的應用程式的業務邏輯。

這意味著,你無需編寫 SQL 語句來讀寫資料庫中的資料,而是你的模型類例項提供了一個 API 來儲存和檢索資料。

Sequelize 是 Node.js 生態系統中一個流行的 ORM,以下是如何使用 Sequelize 的建模方法定義前面章節中相同的 User 模型:

class User extends Model {}
User.init(
{
user_id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: Sequelize.STRING(255),
email: {
type: Sequelize.STRING(255),
unique: true,
},
isAdmin: Sequelize.BOOLEAN,
},
{ sequelize, modelName: 'user' }
)

要使這個 User 類示例正常工作,你仍然需要在資料庫中建立相應的表。使用 Sequelize,你有兩種方法可以做到這一點:

  • 執行 User.sync()(通常不推薦用於生產環境)
  • 使用 Sequelize 遷移 來更改你的資料庫 schema

請注意,你永遠不會手動例項化 User 類(使用 new User(...)),如上一節所示,而是呼叫 User 類的 靜態 方法,這些方法會返回 User 模型例項。

const user = await User.findByPk(42)

findByPk 的呼叫會建立一個 SQL 語句,用於檢索由 ID 值 42 標識的 User 記錄。

生成的 user 物件是 Sequelize 的 Model 類的例項(因為 User 繼承自 Model)。它不是一個 POJO,而是一個實現了 Sequelize 額外行為的物件。

使用 Prisma ORM 進行資料建模

根據你希望在應用程式中使用 Prisma ORM 的哪些部分,資料建模流程會略有不同。以下兩節解釋了僅使用 Prisma Client 和使用 Prisma Client 和 Prisma Migrate 的工作流程。

無論採用哪種方法,使用 Prisma ORM 都不會透過手動定義類、介面或結構體在程式語言中建立應用程式模型。相反,應用程式模型是在你的 Prisma schema 中定義的。

  • 僅使用 Prisma Client:Prisma schema 中的應用程式模型是*根據資料庫 schema 的內省生成的*。資料建模主要在資料庫層面進行。
  • Prisma Client 和 Prisma Migrate:資料建模在 Prisma schema 中透過*手動新增應用程式模型*來完成。Prisma Migrate 將這些應用程式模型對映到底層資料庫中的表(目前僅支援關係型資料庫)。

例如,前一個示例中的 User 模型在 Prisma schema 中將表示如下:

model User {
user_id Int @id @default(autoincrement())
name String?
email String @unique
isAdmin Boolean @default(false)
}

一旦應用程式模型在你的 Prisma schema 中(無論是透過內省還是手動新增),下一步通常是生成 Prisma Client,它提供一個程式設計和型別安全的 API,用於以你的應用程式模型的形狀讀寫資料。

Prisma Client 使用 TypeScript 類型別名 來表示程式碼中的應用程式模型。例如,User 模型在生成的 Prisma Client 庫中將表示如下:

export type User = {
id: number
name: string | null
email: string
isAdmin: boolean
}

除了生成的型別,Prisma Client 還提供了一個數據訪問 API,你可以在安裝 @prisma/client 包後使用它。

import { PrismaClient } from '@prisma/client'
// or
// const { PrismaClient } = require('@prisma/client')

const prisma = new PrismaClient()

// use inside an `async` function to `await` the result
await prisma.user.findUnique(...)
await prisma.user.findMany(...)
await prisma.user.create(...)
await prisma.user.update(...)
await prisma.user.delete(...)
await prisma.user.upsert(...)

僅使用 Prisma Client

當你的應用程式中僅使用 Prisma Client 而*不*使用 Prisma Migrate 時,資料建模需要透過 SQL 在資料庫層面進行。一旦你的 SQL schema 準備就緒,你就可以使用 Prisma 的內省功能將應用程式模型新增到你的 Prisma schema 中。最後,你生成 Prisma Client,它會為你建立型別以及用於讀寫資料庫資料的程式設計 API。

以下是主要工作流程的概述:

  1. 使用 SQL 更改你的資料庫 schema(例如 CREATE TABLE, ALTER TABLE, ...)
  2. 執行 prisma db pull 來內省資料庫並將應用程式模型新增到 Prisma schema
  3. 執行 prisma generate 來更新你的 Prisma Client API

使用 Prisma Client 和 Prisma Migrate

使用 Prisma Migrate 時,你在 Prisma schema 中定義你的應用程式模型,對於關係型資料庫,使用 prisma migrate 子命令生成純 SQL 遷移檔案,你可以在應用之前對其進行編輯。對於 MongoDB,你使用 prisma db push 來代替,它會直接將更改應用到你的資料庫。

以下是主要工作流程的概述:

  1. 在 Prisma schema 中手動更改你的應用程式模型(例如,新增新模型、刪除現有模型等)
  2. 執行 prisma migrate dev 建立並應用遷移,或執行 prisma db push 直接應用更改(兩種情況下都會自動生成 Prisma Client)
© . This site is unofficial and not affiliated with Prisma Data, Inc.