Cloudflare系列(二):Cloudflare KV & D1

cloudflare KV 和 D1 的使用

Posted by Momoka7 on June 17, 2024

集成 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.sqlsql文件用于执行数据库操作。

在此 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 参考