ホームページ >ウェブフロントエンド >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 Client: スキーマに合わせて自動生成されるクエリ ビルダー。データベースへのタイプセーフなアクセスを提供します。
  • 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. Prisma の動作を理解するための基本的な Express API の作成

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
  • GET: http://localhost:5000/api/users
  • GET: http://localhost:5000/api/users/1
  • PUT: 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 - 関連データを含めます。
  • select - 特定のフィールドを選択します。
  • select または 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

過去 1 週間に作成された商品の価格の合計

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
    
  • mode: insensitive: 大文字と小文字を区別しない検索を実行します。

    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 は、まず最初のフィールドで並べ替え、次に最初のフィールドの同一値のグループ内の 2 番目のフィールドで並べ替えます。

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 オプションの使用

並べ替えでの null 値の処理方法を制御できます。 null オプションは、first または last のいずれかに設定できます。

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

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

export default prisma;

デフォルトでは、昇順で並べ替える場合は null 値が最後に配置され、降順で並べ替える場合は最初に配置されます。 null オプションを使用すると、このデフォルトの動作をオーバーライドできます。

Prisma の関係関数

Prisma はデータベース関係をエレガントに処理することに優れています。重要な側面は次のとおりです:

  • スキーマでの関係の定義: @relation 属性を使用して、schema.prisma ファイルでモデル間の関係を直接定義します。

  • 関係のタイプ: Prisma がサポートするもの:

    • 1 対 1: モデル A の 1 つのレコードは、モデル B の 1 つのレコードにのみ関連付けられます。
    • 1 対多: モデル A の 1 つのレコードは、モデル B の複数のレコードに関連付けられます。
    • 多対多: モデル A の複数のレコードは、モデル B の複数のレコードに関連付けられます (結合テーブルが必要です)。

関係の例

前の例の User モデルと Post モデルを使用してみましょう:

mkdir prisma-example
cd prisma-example

これが Prisma ORM をより良く理解するのに役立つことを願っています。
フィードバックやご提案をお気軽にお寄せください。

読んでいただきありがとうございます! ?

以上がPrisma ORM: JS を使用したプロジェクトの開始から終了までの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。