首页 >web前端 >js教程 >Prisma ORM:使用 JS 开始到结束项目

Prisma ORM:使用 JS 开始到结束项目

Linda Hamilton
Linda Hamilton原创
2025-01-16 18:43:15835浏览

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