首頁 >web前端 >js教程 >Prisma ORM:使用 JS 開始到結束項目

Prisma ORM:使用 JS 開始到結束項目

Linda Hamilton
Linda Hamilton原創
2025-01-16 18:43:15837瀏覽

Prisma ORM: Start to End With Project using JS

什麼是棱鏡?

Prisma: Node.js 和 TypeScript 的下一代 ORM

ORM:物件關聯映射是一種使用 OOP 語言與資料庫通訊的方法,無需編寫複雜的查詢。

  • Prisma 旨在讓開發者輕鬆使用資料庫。
  • 它提供類型安全、直覺的 API,並提高開發人員的工作效率。
  • 專注於開發者體驗。

關鍵零件

  • Prisma 架構: 資料庫架構的單一事實來源。定義模型及其關係。
  • Prisma 用戶端: 根據您的架構自動產生的查詢產生器。提供對資料庫的類型安全存取。
  • Prisma Migrate: 用於管理資料庫架構遷移的工具。

為什麼是棱鏡?

  1. 簡化資料庫互動: Prisma ORM 提供直覺的查詢和架構遷移。
  2. 提高程式碼品質: Prisma ORM 產生類型安全的查詢並與流行的 IDE 整合。
  3. 支援多個資料庫:Prisma ORM 讓應用程式的適應和擴展變得更加容易。 (例如 MongoDB、MySQL、MariaDB、PostgreSQL、Microsoft SQL 等)
  4. 緩解傳統 ORM 的問題:Prisma ORM 解決了臃腫的模型實例和不可預測的查詢等問題。

項目設定

1. 項目設定

建立一個新的專案目錄

mkdir prisma-example
cd prisma-example

初始化 Node.js 項目

npm init -y

安裝 Prisma CLI

npm install prisma dotenv express --save-dev

安裝 Prisma 用戶端

npm install @prisma/client --save-dev

這將為您的資料庫安裝 Prisma 用戶端。

2. 初始化Prisma

npx prisma init

這將建立一個 prisma 目錄,其中包含:

  • schema.prisma:您的 Prisma 架構檔案。
  • .env:用於您的資料庫連接字串。

3. 配置資料庫連接

選擇資料庫

該影片可能使用 PostgreSQL,但您可以將其改編為 MySQL、SQLite 或其他。在本範例中,我們將使用 PostgreSQL。

設定 DATABASE_URL

在您的 .env 檔案中,新增連接字串。 PostgreSQL 範例:

DATABASE_URL="postgresql://your_user:your_password@localhost:5432/your_database"

將 your_user、your_password 和 your_database 替換為您的實際憑證。如果您沒有本機 PostgreSQL 伺服器,則需要安裝並設定一個。

4. 定義資料模型 (schema.prisma)

將 prisma/schema.prisma 的內容替換為以下內容:

mkdir prisma-example
cd prisma-example

5.生成Prisma客戶端

npm init -y

這會在node_modules/@prisma/client 中產生類型安全的 Prisma 用戶端。

6. 建立遷移

npm install prisma dotenv express --save-dev

這會在 prisma/migrations 目錄中建立一個新的遷移文件,並將其套用到您的資料庫,從而建立表格。 --name init 為遷移提供了一個描述性名稱。

7. 為 Prisma 設定建立單獨的文件

在根目錄下建立db.config.js文件,新增以下程式碼:

npm install @prisma/client --save-dev

這將建立一個 PrismaClient 的新實例並將其匯出,以便可以在其他文件中使用。 log: ['query'] 選項會將所有查詢記錄到控制台。

8. 建立基本 Express API 來了解 Prisma 工作原理

1. 控制器

在專案根目錄中建立一個controllers.js 檔案。以下是controllers.js檔案中CRUD操作的程式碼:

npx prisma init

2. 路線

在專案根目錄中建立一個routes.js 檔案。以下是routes.js檔案中CRUD操作的程式碼:

DATABASE_URL="postgresql://your_user:your_password@localhost:5432/your_database"

3、伺服器

在專案根目錄中建立一個 server.js 檔案。以下是server.js檔案中CRUD操作的程式碼:

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

datasource db {
    provider = "postgresql" // Or "mysql", "sqlite", etc.
    url      = env("DATABASE_URL")
}

model Post {
    id        String   @id @default(uuid())
    title     String
    content   String?
    createdAt DateTime @default(now())
    author    User     @relation(fields: [user_id], references: [id])
    user_id   Int
}

model User {
    id    Int     @id @default(autoincrement())
    email String  @unique
    name  String?
    posts Post[]
}

9. 運行腳本

npx prisma generate

這將執行腳本,在資料庫中建立使用者和帖子,然後更新使用者並刪除帖子。

您可以使用 Postman 透過以下路線測試 API:

  • POST:http://localhost:5000/api/users
  • 取得:http://localhost:5000/api/users
  • 取得:http://localhost:5000/api/users/1
  • 放置:http://localhost:5000/api/users/1
  • 刪除:http://localhost:5000/api/users/1

在 Postman 中將 POST 請求的正文設定為 JSON,並包含以下資料:

npx prisma migrate dev --name init

Prisma 語法需要考慮的要點

  • findUnique/findFirst - 取得單一記錄,不傳回陣列。
  • findMany - 取得多個記錄,並傳回一個陣列。
  • include - 包含相關數據。
  • 選擇 - 選擇特定欄位。
  • 您只能使用其中一個屬性,可以選擇或包含。

Prisma 語法範例

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient({
    log: ["query"],
});

export default prisma;

有關 Prisma 聚合、過濾、排序和關係的更多信息

1.Prisma 中的聚合函數

Prisma 提供了多種聚合函數,可讓您直接在資料庫查詢中對資料集執行計算。這些函數對於匯總資料和獲得見解非常有用,而無需將大量資料獲取到您的應用程式。

常用聚合函數

  • _count: 計算符合給定條件的記錄數。
  • _avg: 計算數值欄位的平均值。
  • _sum: 計算數字欄位的總和。
  • _min: 找出欄位的最小值。
  • _max: 找出欄位的最大值。

聚合範例

假設我們有以下產品型號:

mkdir prisma-example
cd prisma-example

計算每個類別中的產品數量

npm init -y

計算所有產品的平均價格

npm install prisma dotenv express --save-dev

尋找特定類別中產品的最低和最高價格

npm install @prisma/client --save-dev

上週創建的產品價格總和

npx prisma init

2. Prisma 中的過濾

Prisma 提供了一組豐富的篩選選項,可讓您精確地查詢資料庫。以下是帶有範例的全面概述:

基本過濾

  • 等於(預設): 檢查是否完全相等。

    DATABASE_URL="postgresql://your_user:your_password@localhost:5432/your_database"
    
  • not:否定條件。

    generator client {
        provider = "prisma-client-js"
    }
    
    datasource db {
        provider = "postgresql" // Or "mysql", "sqlite", etc.
        url      = env("DATABASE_URL")
    }
    
    model Post {
        id        String   @id @default(uuid())
        title     String
        content   String?
        createdAt DateTime @default(now())
        author    User     @relation(fields: [user_id], references: [id])
        user_id   Int
    }
    
    model User {
        id    Int     @id @default(autoincrement())
        email String  @unique
        name  String?
        posts Post[]
    }
    

比較運算符

  • gt(大於)、gte(大於或等於)、lt(小於)、lte(小於或等於):用於數字和日期/時間比較。

    npx prisma generate
    

字串過濾器

  • 包含: 檢查字串是否包含子字串。

    npx prisma migrate dev --name init
    
  • startsWith: 檢查字串是否以前綴開頭。

    import { PrismaClient } from "@prisma/client";
    
    const prisma = new PrismaClient({
        log: ["query"],
    });
    
    export default prisma;
    
  • endsWith: 檢查字串是否以後綴結尾。

    import prisma from "./db.config.js";
    
    // create user
    export const createUser = async (req, res) => {
        const { name, email } = req.body;
    
        const existing_user = await prisma.user.findUnique({
            where: {
                email,
            },
        });
    
        if (existing_user) {
            return res.status(400).json({ message: "User already exists" });
        }
    
        const user = await prisma.user.create({
            data: {
                email,
                name,
            },
        });
    
        return res.status(201).json(user);
    };
    
    // create post
    export const createPost = async (req, res) => {
        const { title, content, user_id } = req.body;
    
        const post = await prisma.post.create({
            data: {
                title,
                content,
                user_id,
            },
        });
    
        return res.status(201).json(post);
    };
    
    // get all users
    export const getUsers = async (req, res) => {
        const users = await prisma.user.findMany({
            include: {
                posts: true,
            },
        });
    
        return res.status(200).json(users);
    };
    
    // read specific user by id
    export const getUserById = async (req, res) => {
        const { id } = req.params;
    
        const user = await prisma.user.findUnique({
            where: {
                id: parseInt(id),
            },
            include: {
                posts: true,
            },
        });
    
        if (!user) {
            return res.status(404).json({ message: "User not found" });
        }
    
        return res.status(200).json(user);
    };
    
    // update user
    export const updateUser = async (req, res) => {
        const { id } = req.params;
        const { name, email } = req.body;
    
        const user = await prisma.user.update({
            where: {
                id: parseInt(id),
            },
            data: {
                name,
                email,
            },
        });
    
        return res.status(200).json(user);
    };
    
    // delete user
    export const deleteUser = async (req, res) => {
        const { id } = req.params;
    
        const user = await prisma.user.delete({
            where: {
                id: parseInt(id),
            },
        });
    
        return res.status(200).json(user);
    };
    
    // create similar for post
    
  • 模式:不敏感: 執行不區分大小寫的搜尋。

    import express from "express";
    import {
        createUser,
        createPost,
        getUsers,
        getUserById,
        updateUser,
        deleteUser,
    } from "./controllers.js";
    
    const router = express.Router();
    
    router.post("/users", createUser);
    router.get("/users", getUsers);
    router.get("/users/:id", getUserById);
    router.put("/users/:id", updateUser);
    router.delete("/users/:id", deleteUser);
    // create similar for post
    router.post("/posts", createPost);
    // router.get('/posts', getPosts);
    // router.get('/posts/:id', getPostById);
    // router.put('/posts/:id', updatePost);
    // router.delete('/posts/:id', deletePost);
    
    export default router;
    

列表過濾器

  • in: 檢查清單中是否有值。

    import express from "express";
    import dotenv from "dotenv";
    import router from "./routes.js";
    
    dotenv.config();
    
    const app = express();
    
    app.use(express.json());
    app.use("/api", router);
    
    const PORT = process.env.PORT || 5000;
    
    app.listen(PORT, () => {
        console.log(`Server running on port ${PORT}`);
    });
    
  • notIn: 檢查某個值是否出現在清單中。

    node index.js
    

邏輯運算符

  • AND: 使用邏輯 AND 組合多個條件。

    {
        "name": "John Doe",
        "email": "sample@example.com"
    }
    
  • OR: 使用邏輯 OR 組合多個條件。

    // get all posts of a user with id
    const user = await prisma.user.findUnique({
        where: {
            id: parseInt(id),
        },
        include: {
            posts: true,
        },
    });
    
    // select specific fields of user with post details
    const user = await prisma.user.findUnique({
        where: {
            id: parseInt(id),
        },
        select: {
            name: true,
            posts: {
                select: {
                    title: true,
                    content: true,
                },
            },
        },
    });
    
    // get all users name with their posts count (Aggregation)
    const req_data = await prisma.user.findMany({
        select: {
            id: true,
            name: true,
            _count: {
                select: {
                    post: true,
                },
            },
        },
    });
    
  • NOT: 否定一組條件。

    model Product {
        id        Int      @id @default(autoincrement())
        name      String
        price     Float
        category  String
        createdAt DateTime @default(now())
    }
    

嵌套過濾器(關係過濾)

您可以依照相關型號進行過濾。

mkdir prisma-example
cd prisma-example

過濾可選關係

npm init -y

組合過濾器

您可以組合這些運算子來實現複雜的過濾邏輯。

npm install prisma dotenv express --save-dev

這些範例涵蓋了 Prisma 中最常見的過濾場景。透過組合這些運算子和巢狀過濾器,您可以建立非常精確的查詢來檢索所需的確切資料。請記得查閱 Prisma 官方文件以獲取最新、詳細的資訊。

Prisma 中的訂單記錄

Prisma 的 orderBy 選項可讓您對查詢結果進行排序。以下是一些示範其用法的範例:

基本訂購

  • 升序(預設):

    npm install @prisma/client --save-dev
    
  • 降序:

    npx prisma init
    

按多個欄位排序

您可以指定多個欄位進行排序,每個欄位都有不同的方向。 Prisma 將首先按第一個欄位排序,然後按第一個欄位中相同值組中的第二個欄位排序,依此類推。

DATABASE_URL="postgresql://your_user:your_password@localhost:5432/your_database"

在此範例中,貼文將主要按作者姓名升序排序。如果多個帖子具有相同的作者,則它們將按標題降序排列。

按嵌套字段(關係)排序

如上例所示,您可以依照相關模型上的欄位進行排序。

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

datasource db {
    provider = "postgresql" // Or "mysql", "sqlite", etc.
    url      = env("DATABASE_URL")
}

model Post {
    id        String   @id @default(uuid())
    title     String
    content   String?
    createdAt DateTime @default(now())
    author    User     @relation(fields: [user_id], references: [id])
    user_id   Int
}

model User {
    id    Int     @id @default(autoincrement())
    email String  @unique
    name  String?
    posts Post[]
}

這將根據作者的電子郵件地址對貼文進行排序。

按日期/時間欄位排序

您也可以按日期和時間欄位排序。

npx prisma generate

依與篩選欄位不同的欄位排序

您可以按一個欄位進行過濾並按另一個欄位進行排序。例如,您可能想要查找名稱中包含“test”的所有用戶,但按電子郵件地址對他們進行排序:

npx prisma migrate dev --name init

使用 null 選項

您可以控制排序中如何處理空值。 nulls 選項可以設定為第一個或最後一個。

import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient({
    log: ["query"],
});

export default prisma;

預設情況下,依升序排序時,空值放在最後;依降序排序時,空值放在最前面。 nulls 選項可讓您覆寫此預設行為。

Prisma 中的關係函數

Prisma 擅長優雅地處理資料庫關係。以下是關鍵方面:

  • 在架構中定義關係:您可以使用 @relation 屬性直接在 schema.prisma 檔案中定義模型之間的關係。

  • 關係類型: Prisma 支援:

    • 一對一:模型 A 中的一筆記錄與模型 B 中的一筆記錄恰好相關。
    • 一對多:模型 A 中的一筆記錄與模型 B 中的多筆記錄相關。
    • 多對多:模型A中的多筆記錄與模型B中的多筆記錄相關(需要連接表)。

關係範例

讓我們使用前面範例中的 User 和 Post 模型:

mkdir prisma-example
cd prisma-example

希望這可以幫助您更好地理解 Prisma ORM。
歡迎提出您的回饋和建議。

感謝您的閱讀! ?

以上是Prisma ORM:使用 JS 開始到結束項目的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn