sqlite3 + prisma challenge
これをやる
npx prisma migrate dev --name init
までやると、DBが生成される。
% tree -I node_modules
.
├── package-lock.json
├── package.json
├── prisma
│ ├── dev.db
│ ├── dev.db-journal
│ ├── migrations
│ │ ├── 20220726082340_init
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ └── schema.prisma
└── tsconfig.json
3 directories, 8 files
DBをみるには、sqlite3 prisma/dev.db
を実行
sqlite> .tables
Post User _prisma_migrations
sqlite> .databases
main: /Users/sandbox/sql/hello-prisma/prisma/dev.db r/w
DB投入スクリプト。
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient()
const main = async () => {
const user = await prisma.user.create({
data: {
name: 'Alice',
email: 'alice@example.com'
}
})
console.log(user)
}
main()
.catch(e => {
console.log(e)
throw e
})
.finally(async () => {
await prisma.$disconnect()
})
*.prisma
で定義してmigrateしておくと、メソッドが生える仕様なのかな。
引数でオブジェクトを投げる形の方が、抜け漏れが起きにくそうな印象はあるかもしれない。
型もあるので、動的に内容が変わるケースとかでもTSで頑張れる。
const userData: Omit<User, 'id'> = {
name: "John",
email: 'john@example.com'
}
const user = await prisma.user.create({
data: userData
})
AUTOINCREMENT
な値(チュートリアルでのid
)も必須になるので、こっちでやる時は適宜Omit
することになりそうかも。
SQLでデータをみる。
sqlite> select * from User;
id|email|name
1|alice@example.com|Alice
2|john@example.com|John
3|jane@example.com|Jane
4|Jack85@hotmail.com|Chanelle
Omit<User, 'id'>
だとRelation張ってる値はダメっぽい。
クイックスタートだとこれ。
posts Post[]
こんな書き方になる。
const user = await prisma.user.create({
data: {
...userData,
posts: {
}
}
})
わかった。
Prisma.<ModelName>CreateInput
を使うと良さそう。
import { Prisma, PrismaClient } from "@prisma/client";
import { faker } from '@faker-js/faker';
const userData: Prisma.UserCreateInput = {
name: faker.name.firstName(),
email: faker.internet.email(),
posts: {
create: {
title: faker.lorem.text(),
content: faker.lorem.paragraphs(),
published: true,
}
}
}
const user = await prisma.user.create({
data: userData
})
整理して記事にした。
データ探索。
どこかしらDynamoDBとかStripeのSearch APIっぽさを感じるので、SQL苦手でも使いやすい感じはあるかもしれない。
const users = await prisma.user.findMany({
where: {
id: {
lte: 2
}
}
})
日本語のチートシート
DynamoDB GetItem相当のメソッド
const user = await prisma.user.findUnique({
where: {
id: 1
}
})
console.log(user)
reltion先のデータでもクエリできる。
const users = await prisma.user.findMany({
where: {
posts: {
some: {
published: true
}
}
},
include: {
posts: true,
},
})
このあたり、型定義か英語のDocs読まないとなので難易度ちょっと高いと感じる人はいるかも?
.select
で指定ができる。
const posts = await prisma.post.findMany({
where: {
published_at: {
gte: dayjs().subtract(1, 'year').toDate()
}
},
select: {
title: true,
id: true,
}
})
ただしinclude
との併用はできないっぽい。
なるほど、select
のネストか。
const posts = await prisma.post.findMany({
where: {
published_at: {
gte: dayjs().subtract(1, 'year').toDate()
}
},
select: {
title: true,
id: true,
author: {
select: {
name: true
}
}
}
})
これもまとめた。
Faker.jsを使うと無限に遊べる。
@faker-js/faker
がコミュニティForkなので、インストールするライブラリを間違えないように注意。
const userData: Omit<User, 'id'> = {
name: faker.name.firstName(),
email: faker.internet.email(),
}
const user = await prisma.user.create({
data: userData
})
ER図の出力もできるらしい。
Install
yarn add -D prisma-erd-generator @mermaid-js/mermaid-cli
schema.prisma
+generator erd {
+ provider = "prisma-erd-generator"
+ output = "../ERD.svg"
+}
Execute
npx prisma generate
Appendix
SVGだけでなくPNGもいけた。
かくちょうしをかえる
ERを先に書いた方がいいのでは・・・って思うので、コードから生成ってどうなんだろ。
「手書きのラフとかでOKになって、清書しなくて済む」とか、「prisma migrate
前のレビューに使える」とかそんなところかな?
Migration
公開日を足してみる
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
+ published_at DateTime
author User @relation(fields: [authorId], references: [id])
authorId Int
}
レコードが既にある場合、エラーが出る。
Error:
⚠️ We found changes that cannot be executed:
• Step 0 Added the required column `published_at` to the `Post` table without a default value. There are 4 rows in this table, it is not possible to execute this step.
optionalにするか、@default
で初期値を入れる。
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
- published_at DateTime
+ published_at DateTime?
author User @relation(fields: [authorId], references: [id])
authorId Int
}
これでいける。
% npx prisma migrate dev --name add_published_at
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": SQLite database "dev.db" at "file:./dev.db"
Applying migration `20220726132000_add_published_at`
The following migration(s) have been created and applied from new schema changes:
migrations/
└─ 20220726132000_add_published_at/
└─ migration.sql
Your database is now in sync with your schema.
✔ Generated Prisma Client (4.1.0 | library) to ./node_modules/@prisma/client in
65ms
✔ Generated Entity-relationship-diagram to ./ERD.png in 1.75s
DateTime
はDate
オブジェクトをセットする。
const userData: Prisma.UserCreateInput = {
name: faker.name.firstName(),
email: faker.internet.email(),
posts: {
create: {
title: faker.lorem.text(),
content: faker.lorem.paragraphs(),
published: true,
published_at: dayjs().subtract(2, 'month').toDate(),
}
}
}
WHEREでもDateを使う。
const users = await prisma.user.findMany({
where: {
posts: {
every: {
published_at: {
lte: dayjs().add(1, 'day').toDate(),
not: null,
}
}
}
},
include: {
posts: true,
},
})
記事にまとめた。
PrismaでのWordPressのテーブル定義についてっぽいIssueを見つけた。
このあたりうまく使えば、すでにあるWordPressの記事データをPrismaでとってくるみたいなこともできる・・・のかな。