操作
Deno KV API 提供了一组可以对键空间执行的操作。
有两种操作可以从存储中读取数据,以及五种操作可以将数据写入存储。
读取操作可以在强一致性模式或最终一致性模式下执行。强一致性模式保证读取操作将返回最近写入的值。最终一致性模式可能会返回过时值,但速度更快。
写入操作始终在强一致性模式下执行。
get
跳转到标题
get
操作返回与给定键关联的值和版本戳。如果值不存在,则 get 返回一个 null
值和版本戳。
有两个 API 可用于执行 get
操作。该 Deno.Kv.prototype.get(key, options?)
API,它可用于读取单个键,以及 Deno.Kv.prototype.getMany(keys, options?)
API,它可用于一次读取多个键。
Get 操作在所有一致性模式下都作为“快照读取”执行。这意味着,当一次检索多个键时,返回的值将彼此一致。
const res = await kv.get<string>(["config"]);
console.log(res); // { key: ["config"], value: "value", versionstamp: "000002fa526aaccb0000" }
const res = await kv.get<string>(["config"], { consistency: "eventual" });
console.log(res); // { key: ["config"], value: "value", versionstamp: "000002fa526aaccb0000" }
const [res1, res2, res3] = await kv.getMany<[string, string, string]>([
["users", "sam"],
["users", "taylor"],
["users", "alex"],
]);
console.log(res1); // { key: ["users", "sam"], value: "sam", versionstamp: "00e0a2a0f0178b270000" }
console.log(res2); // { key: ["users", "taylor"], value: "taylor", versionstamp: "0059e9035e5e7c5e0000" }
console.log(res3); // { key: ["users", "alex"], value: "alex", versionstamp: "00a44a3c3e53b9750000" }
list
跳转到标题
list
操作返回与给定选择器匹配的键列表。这些键的关联值和版本戳也会返回。可以使用 2 个不同的选择器来过滤匹配的键。
prefix
选择器匹配所有以给定前缀键部分开头的键,但不包括键的完全匹配。前缀选择器可以选择性地给出 start
或 end
键来限制返回的键范围。start
键是包含的,end
键是排除的。
range
选择器匹配所有在给定 start
和 end
键之间按字典顺序排列的键。start
键是包含的,end
键是排除的。
注意:在使用前缀选择器的情况下,
prefix
键必须仅包含完整(而不是部分)键部分。例如,如果键["foo", "bar"]
存在于存储中,则前缀选择器["foo"]
将匹配它,但前缀选择器["f"]
不会。
列表操作可以选择性地给出 limit
来限制返回的键数。
可以使用 Deno.Kv.prototype.list<string>(selector, options?)
方法执行列表操作。此方法返回一个 Deno.KvListIterator
,可用于迭代返回的键。这是一个异步迭代器,可以与 for await
循环一起使用。
// Return all users
const iter = kv.list<string>({ prefix: ["users"] });
const users = [];
for await (const res of iter) users.push(res);
console.log(users[0]); // { key: ["users", "alex"], value: "alex", versionstamp: "00a44a3c3e53b9750000" }
console.log(users[1]); // { key: ["users", "sam"], value: "sam", versionstamp: "00e0a2a0f0178b270000" }
console.log(users[2]); // { key: ["users", "taylor"], value: "taylor", versionstamp: "0059e9035e5e7c5e0000" }
// Return the first 2 users
const iter = kv.list<string>({ prefix: ["users"] }, { limit: 2 });
const users = [];
for await (const res of iter) users.push(res);
console.log(users[0]); // { key: ["users", "alex"], value: "alex", versionstamp: "00a44a3c3e53b9750000" }
console.log(users[1]); // { key: ["users", "sam"], value: "sam", versionstamp: "00e0a2a0f0178b270000" }
// Return all users lexicographically after "taylor"
const iter = kv.list<string>({ prefix: ["users"], start: ["users", "taylor"] });
const users = [];
for await (const res of iter) users.push(res);
console.log(users[0]); // { key: ["users", "taylor"], value: "taylor", versionstamp: "0059e9035e5e7c5e0000" }
// Return all users lexicographically before "taylor"
const iter = kv.list<string>({ prefix: ["users"], end: ["users", "taylor"] });
const users = [];
for await (const res of iter) users.push(res);
console.log(users[0]); // { key: ["users", "alex"], value: "alex", versionstamp: "00a44a3c3e53b9750000" }
console.log(users[1]); // { key: ["users", "sam"], value: "sam", versionstamp: "00e0a2a0f0178b270000" }
// Return all users starting with characters between "a" and "n"
const iter = kv.list<string>({ start: ["users", "a"], end: ["users", "n"] });
const users = [];
for await (const res of iter) users.push(res);
console.log(users[0]); // { key: ["users", "alex"], value: "alex", versionstamp: "00a44a3c3e53b9750000" }
列表操作以批处理方式从存储中读取数据。可以使用 batchSize
选项控制每个批处理的大小。默认批处理大小为 500 个键。批处理中的数据在一个快照读取中读取,因此值彼此一致。一致性模式适用于读取的每批数据。跨批次,数据不一致。批次之间的边界在 API 中不可见,因为迭代器返回单个键。
通过将 reverse
选项设置为 true
,可以以反向顺序执行列表操作。这将按字典顺序以降序返回键。start
和 end
键仍然分别是包含的和排除的,并且仍然解释为按字典顺序升序。
// Return all users in reverse order, ending with "sam"
const iter = kv.list<string>({ prefix: ["users"], start: ["users", "sam"] }, {
reverse: true,
});
const users = [];
for await (const res of iter) users.push(res);
console.log(users[0]); // { key: ["users", "taylor"], value: "taylor", versionstamp: "0059e9035e5e7c5e0000" }
console.log(users[1]); // { key: ["users", "sam"], value: "sam", versionstamp: "00e0a2a0f0178b270000" }
注意:在上面的示例中,我们将
start
键设置为["users", "sam"]
,即使返回的第一个键是["users", "taylor"]
。这是因为即使在反向顺序执行列表操作时(按字典顺序以降序返回键),start
和end
键始终按字典顺序升序进行评估。
set
跳转到标题
set
操作在存储中设置键的值。如果键不存在,则会创建它。如果键已经存在,则会覆盖其值。
可以使用 Deno.Kv.prototype.set(key, value)
方法执行 set
操作。此方法返回一个 Promise
,它解析为一个 Deno.KvCommitResult
对象,其中包含提交的 versionstamp
。
Set 操作始终在强一致性模式下执行。
const res = await kv.set(["users", "alex"], "alex");
console.log(res.versionstamp); // "00a44a3c3e53b9750000"
delete
跳转到标题
delete
操作从存储中删除键。如果键不存在,则操作为空操作。
可以使用 Deno.Kv.prototype.delete(key)
方法执行 delete
操作。
删除操作始终以强一致性模式执行。
await kv.delete(["users", "alex"]);
sum
跳转到标题
sum
操作会原子地将一个值添加到存储中的键。如果键不存在,则使用该和的值创建该键。如果该键已存在,则将其值添加到该和中。
sum
操作只能作为原子操作的一部分执行。可以使用 Deno.AtomicOperation.prototype.mutate({ type: "sum", value })
方法将和变异添加到原子操作中。
sum
操作只能对 Deno.KvU64
类型的执行。操作数和存储中的值都必须是 Deno.KvU64
类型。
如果键的新值大于 2^64 - 1
或小于 0
,则求和操作将绕回。例如,如果存储中的值为 2^64 - 1
,而操作数为 1
,则新值为 0
。
求和操作始终以强一致性模式执行。
await kv.atomic()
.mutate({
type: "sum",
key: ["accounts", "alex"],
value: new Deno.KvU64(100n),
})
.commit();
min
跳转到标题
min
操作会原子地将键设置为其当前值和给定值的最小值。如果键不存在,则使用给定值创建该键。如果该键已存在,则将其值设置为其当前值和给定值的最小值。
min
操作只能作为原子操作的一部分执行。可以使用 Deno.AtomicOperation.prototype.mutate({ type: "min", value })
方法将最小变异添加到原子操作中。
min
操作只能对 Deno.KvU64
类型的执行。操作数和存储中的值都必须是 Deno.KvU64
类型。
最小值操作始终以强一致性模式执行。
await kv.atomic()
.mutate({
type: "min",
key: ["accounts", "alex"],
value: new Deno.KvU64(100n),
})
.commit();
max
跳转到标题
max
操作会原子地将键设置为其当前值和给定值的最大值。如果键不存在,则使用给定值创建该键。如果该键已存在,则将其值设置为其当前值和给定值的最小值。
max
操作只能作为原子操作的一部分执行。可以使用 Deno.AtomicOperation.prototype.mutate({ type: "max", value })
方法将最大值变异添加到原子操作中。
max
操作只能对 Deno.KvU64
类型的执行。操作数和存储中的值都必须是 Deno.KvU64
类型。
最大值操作始终以强一致性模式执行。
await kv.atomic()
.mutate({
type: "max",
key: ["accounts", "alex"],
value: new Deno.KvU64(100n),
})
.commit();
watch
跳转到标题
watch
操作接受一个键数组,并返回一个 ReadableStream
,每当任何监视的键更改其 versionstamp
时,它都会发出一个新值。发出的值是一个 Deno.KvEntryMaybe 对象数组。
请注意,返回的流不会返回所有监视的键的每个中间状态,而是使用最新状态来保持您对键的最新状态。这意味着如果一个键被快速修改多次,您可能不会收到每次更改的通知,但您会收到该键的最新状态。
const db = await Deno.openKv();
const stream = db.watch([["foo"], ["bar"]]);
for await (const entries of stream) {
entries[0].key; // ["foo"]
entries[0].value; // "bar"
entries[0].versionstamp; // "00000000000000010000"
entries[1].key; // ["bar"]
entries[1].value; // null
entries[1].versionstamp; // null
}