集成 KV
Workers KV 是一种数据存储,可让您全局存储和检索数据。借助 Workers KV,您可以构建动态且高性能的 API 和网站,以支持低延迟的高读取量。
1. 添加 KV
使用npx wrangler kv namespace查看操作 KV 的相关指令。
1
2
3
4
Commands:
wrangler kv namespace create <namespace> Create a new namespace
wrangler kv namespace list Outputs a list of all KV namespaces associated with your account id.
wrangler kv namespace delete Deletes a given namespace.
创建一个新的 KV 命名空间:npx wrangler@latest kv namespace create CACHE
使用控制台所输出的信息,修改wrangler.toml,添加如下:
1
2
3
[[kv_namespaces]]
binding = "CACHE"
id = "98a34befa74248f7a370a365a29af03f"
2. 使用 KV
需求场景如下:获取指定用户的 github 仓库列表,将已请求过用户 github 仓库列表信息存储到 KV 中,之后再请求同一个用户的数据时,则直接从 KV 中获取。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
app.get("/repos/:username", async (c) => {
const username = c.req.param("username");
//使用c.env.{toml文件中绑定的名称,这里是CACHE}获取KV实例
//KV.get(key, format)获取指定key的value,第二个参数为数据格式
const cached = await c.env.CACHE.get(`repos:${username}`, "json");
if (cached) {
//KV中有缓存直接返回
return c.json(cached);
} else {
//否则请求数据,并放入KV中
const resp = await fetch(`https://api.github.com/users/${username}/repos`, {
headers: {
"User-Agent": "CF Workers",
},
});
const data = await resp.json();
//KV.get(key, value, option)设置键值对,在option中可以设置过期时间等
await c.env.KV.put(`repos:${username}`, JSON.stringify(data), {
expirationTtl: 60,
});
return c.json(data);
}
});
集成 D1
D1 基于 SQLite 构建,是 Cloudflare 首个可查询关系数据库。通过导入数据或定义表格并在 Worker 中或通过 API 编写查询来创建整个数据库。
1. 添加 D1
使用npx wrangler d1来查看 D1 的一些操作指令。
1
2
3
4
5
6
7
8
9
10
11
Commands:
wrangler d1 list List D1 databases
wrangler d1 info <name> Get information about a D1 database, including the current database size and state.
wrangler d1 insights <name> Experimental command. Get information about the queries run on a D1 database.
wrangler d1 create <name> Create D1 database
wrangler d1 delete <name> Delete D1 database
wrangler d1 backup Interact with D1 Backups
wrangler d1 execute <database> Executed command or SQL file
wrangler d1 export <name> Export the contents or schema of your database as a .sql file
wrangler d1 time-travel Use Time Travel to restore, fork or copy a database at a specific point-in-time.
wrangler d1 migrations Interact with D1 Migrations
使用npx wrangler d1 create movie来创建一个数据库,这里创建一个名为movie的数据库。
使用控制台所输出的信息,修改wrangler.toml,添加如下:
1
2
3
4
[[d1_databases]]
binding = "DB" # i.e. available in your Worker on env.DB
database_name = "movie"
database_id = "fe69676b-10bb-47bb-8a2e-5fce9f793b0a"
2. 使用 D1
1. 使用 migrations 管理数据库
migrations 可以帮助管理数据库的操作版本(一些地方类似于 git)
使用npx wrangler d1 migrations查看 migrations 相关命令:
1
2
3
4
Commands:
wrangler d1 migrations list <database> List your D1 migrations
wrangler d1 migrations create <database> <message> Create a new Migration
wrangler d1 migrations apply <database> Apply D1 Migrations
从指令列表中可以看出,migrations 基础操作对象是数据库。
按照如下步骤添加表和数据:
1. 添加表
npx wrangler d1 migrations create movie create-tables, 由于是第一次执行migrations命令,会询问是否添加一个migrations文件夹由于管理,并在其目录下创建一个0001_create-tables.sql的sql文件用于执行数据库操作。
在此 sql 文件下添加如下建表语句:
1
2
3
4
5
6
7
DROP TABLE IF EXISTS movies;
CREATE TABLE movies (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
release_date TEXT NOT NULL,
rating INT NOT NULL
);
执行npx wrangler d1 migrations apply movie即可执行migrations下待执行的sql文件。
2. 添加数据
和上述步骤类似,执行npx wrangler d1 migrations create movie add-movies,编辑其新建的0002_add-movies.sql:
1
2
3
4
5
6
INSERT INTO movies (title, release_date, rating) VALUES
('The Shawshank Redemption', '1994-09-23', 6),
('The Godfather', '1972-03-24', 10),
('The Dark Knight', '2008-07-18', 7),
('The Godfather: Part II', '1974-12-20', 9),
('12 Angry Men', '1957-04-10', 8);
执行npx wrangler d1 migrations apply movie应用更改。
3. 同步到 cloudflare 远程 D1
上述操作目前只会在本地生效,在本地部署dev模式下可以使用,若要在部署后的 wokers 中使用最新的数据库,需要将其应用在远程 D1 上。
在apply指令上添加--remote参数执行即可:npx wrangler d1 migrations apply movie --remote。
2. 在代码中使用 D1
添加一些请求路径来执行数据库查询、修改等操作:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
app.get("/movies", async (c) => {
// 使用c.env.DB来获取D1实例,这里`DB`是在wrangler.toml中的bind名称
// prepare方法中添加数据库操作语句
// all方法进行查询并获取结果
const { results: movies } = await c.env.DB.prepare(
"select * from movies"
).all();
return c.json(movies);
});
app.get("/favorites", async (c) => {
const { results: favorites } = await c.env.DB.prepare(
"select * from movies order by rating desc limit 3"
).all();
return c.json(favorites);
});
app.post("/movies/:id", async (c) => {
//从post请求体中获取数据
const body = await c.req.json();
// 使用`?1 ?2 ...`这样的占位符来表示动态数据
// 使用bind方法来替换占位符为实际的数据
// run方法执行UPDATE、DELETE 或 INSERT 等写入操作。
const result = await c.env.DB.prepare(
"UPDATE movies SET rating = ?1 WHERE id = ?2 RETURNING *"
)
.bind(body.rating, c.req.param("id"))
.run();
const ok = result.success;
return c.json({ ok });
});
更多数据库操作API 参考