记录博客文章浏览次数

kaichikaichi • 2021-12-04

2 分钟0 阅读

文章的阅读数量数据我们储存在 Severless 数据库 PlantScale 中,创建好账户和数据库后就可以开始使用了,具体的步骤参考官方文档

连接数据库

测试连接数据库

先用 PlanetScale CLI 看能否连接上数据库。首次连接需要先登录。

// 登陆
$ pscale auth login

// 连接数据库指定分支
$ pscale shell <database-name> <branch>

ORM

$ pnpm i -D prisma

Prisma Schema

创建 shadow 分支以供调试。

点击 PlanetScale 右上角的 connect 按钮,创建新密码,下方选择 Prisma,复制。url 添加到环境变量。

.env
DATABASE_URL=<复制的 url>

Schema 配置详解

prisma/prisma.schema
datasource db {
  url               = env("DATABASE_URL") // 正式
  shadowDatabaseUrl = env("SHADOW_DATABASE_URL") // 测试
  provider          = "mysql"
}

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

创建表

我们先需要在数据库里创建表存储数据,修改 schema.prisma。

datasource db {
  url               = env("DATABASE_URL") // 正式
  shadowDatabaseUrl = env("SHADOW_DATABASE_URL") // 测试
  provider          = "mysql"
}

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

+ model views {
+   slug  String @id @db.VarChar(128)
+   count BigInt @default(1)
+ }

Migrate

$ pnpm exec prisma db push

远程连接数据库,需要将 schema push 到远程,而不是直接 migrate,参考

migrate 成功后,查看 views 表是否创建成功。

blog/shadow> show tables;
+----------------+
| Tables_in_blog |
+----------------+
| views          |
+----------------+

记录文章浏览数据

初始化 Prisma Client。

lib/prisma.ts
import { PrismaClient } from "@prisma/client";

declare global {
  var prisma: PrismaClient | undefined;
}

export const prisma = global.prisma || new PrismaClient();

if (process.env.NODE_ENV !== "production") global.prisma = prisma;

记录浏览次数 API

pages/api/views/[slug].ts
if (req.method === "POST") {
  const upsertViews = await prisma.views.upsert({
    where: { slug },
    create: {
      slug
    },
    update: {
      count: {
        increment: 1
      }
    }
  });

  return res.status(200).json({
    total: upsertViews.count.toString()
  });

查询浏览次数 API

pages/api/views/[slug].ts
if (req.method === "GET") {
  const views = await prisma.views.findUnique({
    where: {
      slug
    }
  });

  return res.status(200).json({ total: views?.count.toString() });
}

在文章页面打开时记录浏览

useEffect(() => {
  const registerView = () =>
    fetch(`/api/views/${post.slug}`, {
      method: 'POST'
    });

  registerView();
}, [post.slug]);
在 Github 上编辑