Deno KV 快速入门
Deno KV 是一个
key-value 数据库
直接内置于 Deno 运行时中,可在
Deno.Kv
命名空间 中使用。它可用于
许多种数据存储用途,但在存储简单数据结构并且需要非常快速读写的情况下表现出色。Deno
KV 可用于 Deno CLI 和 Deno Deploy 中。
Deno 的 KV 及其相关的云基元 API,如队列和定时任务,目前仍处于实验性阶段,可能会发生变化。尽管我们尽力确保数据持久性,但特别是在 Deno 更新时,仍然存在数据丢失的可能性。
在启动使用 KV 的 Deno 程序时,需要添加--unstable
标志,如下所示:
deno run -A --unstable my_kv_code.ts
让我们来看看 Deno KV 的主要特点。
打开数据库
在你的 Deno 程序中,你可以使用
Deno.openKv()
获取一个 KV
数据库的引用。你可以选择传入一个可选的文件系统路径,用于存储数据库,否则将基于你的脚本的当前工作目录为你创建一个。
const kv = await Deno.openKv();
创建、更新和读取键值对
Deno KV 中的数据存储为键值对,类似于 JavaScript 对象字面量或
Map
的属性。键 表示为 JavaScript 类型的数组,如
string
、number
、bigint
或 boolean
。值可以是任意的 JavaScript
对象。在此示例中,我们创建一个表示用户 UI 首选项的键值对,并使用
kv.set()
保存它。
const kv = await Deno.openKv();
const prefs = {
username: "ada",
theme: "dark",
language: "en-US",
};
const result = await kv.set(["preferences", "ada"], prefs);
一旦设置了键值对,你可以使用
kv.get()
从数据库中读取它:
const entry = await kv.get(["preferences", "ada"]);
console.log(entry.key);
console.log(entry.value);
console.log(entry.versionstamp);
get
和 list
操作 都返回一个
KvEntry 对象,具有以下属性:
key
- 用于设置值的数组键value
- 为此键设置的 JavaScript 对象versionstamp
- 用于确定是否已更新键的生成值。
set
操作还用于更新已经存在于给定键的对象。当键的值被更新时,它的
versionstamp
将更改为新生成的值。
列出多个键值对
要获取有限数量的键的值,你可以使用
kv.getMany()
。将多个键作为参数传递,你将收到每个键的值数组。注意,如果给定键的值不存在,值和版本戳可以为
null
。
const kv = await Deno.openKv();
const result = await kv.getMany([
["preferences", "ada"],
["preferences", "grace"],
]);
result[0].key; // ["preferences", "ada"]
result[0].value; // { ... }
result[0].versionstamp; // "00000000000000010000"
result[1].key; // ["preferences", "grace"]
result[1].value; // null
result[1].versionstamp; // null
通常,检索共享给定前缀的所有键值对的列表是有用的。使用
kv.list()
可以执行此类操作。在此示例中,我们获取共享 "preferences"
前缀的键值对列表。
const kv = await Deno.openKv();
const entries = kv.list({ prefix: ["preferences"] });
for await (const entry of entries) {
console.log(entry.key); // ["preferences", "ada"]
console.log(entry.value); // { ... }
console.log(entry.versionstamp); // "00000000000000010000"
}
返回的键是基于前缀后的键的下一个组件按字典顺序排序的。因此,具有这些键的 KV 对:
["preferences", "ada"]
["preferences", "bob"]
["preferences", "cassie"]
将按 kv.list()
的顺序返回。
读操作可以在 强一致性或最终一致性模式 中执行。强一致性模式保证读取操作将返回最近写入的值。最终一致性模式可能返回陈旧的值,但更快。相比之下,写操作始终在强一致性模式下执行。
删除键值对
你可以使用
kv.delete()
从数据库中删除键。如果给定键找不到值,将不执行任何操作。
const kv = await Deno.openKv();
await kv.delete(["preferences", "alan"]);
原子事务
Deno KV 能够执行原子事务,这使你能够有条件地执行一个或多个数据操作。在下面的示例中,仅当首选项对象尚未创建时,我们创建一个新的首选项对象。
const kv = await Deno.openKv();
const key = ["preferences", "alan"];
const value = {
username: "alan",
theme: "light",
language: "en-GB",
};
const res = await kv
.atomic()
.check({ key, versionstamp: null }) // `null` versionstamps mean 'no value'
.set(key, value)
.commit();
if (res.ok) {
console.log("首选项尚未存在。已插入!");
} else {
console.error("首选项已经存在。");
}
在 Deno KV 中了解更多关于事务的内容 在此处。
使用二级索引改进查询
辅助索引 通过多个键存储相同的数据,使得获取所需数据的查询变得更加简单。假设我们需要通过用户名和电子邮件两种方式访问用户偏好设置。为了实现这一点,您可以提供一个函数,该函数包装了保存偏好设置的逻辑,以创建两个索引。
const kv = await Deno.openKv();
async function savePreferences(prefs) {
const key = ["preferences", prefs.username];
// 设置主键
const r = await kv.set(key, prefs);
// 将辅助键的值设置为主键
await kv.set(["preferencesByEmail", prefs.email], key);
return r;
}
async function getByUsername(username) {
// 如之前所述...
const r = await kv.get(["preferences", username]);
return r;
}
async function getByEmail(email) {
// 通过电子邮件查找键,然后再次查找实际数据
const r1 = await kv.get(["preferencesByEmail", email]);
const r2 = await kv.get(r1.value);
return r2;
}
在手册中了解更多关于二级索引的内容。
生产用途
Deno KV 可在 Deno Deploy 上的实时应用程序中使用。在生产中,Deno KV 由 FoundationDB 支持,这是由 Apple 创建的开源键值存储。
无需额外配置,你可以在 Deploy 上运行使用 KV 的 Deno 程序 - 当你的代码需要时,将为你提供新的 Deploy 数据库。在此处了解更多关于 Deno Deploy 上的 Deno KV 的信息。
下一步
到目前为止,你仅仅开始了解 Deno KV 的基础知识。请确保查看我们的关于 Deno KV 键空间 的指南,以及这里的教程和示例应用程序集合。