# @convex-dev/sharded-counter 中文文档

规范地址：https://npmcn.com/package/%40convex-dev/sharded-counter/

版本：0\.2\.3
npm 元数据更新时间：2026-10-10T00:52:35.515Z
中文译文更新时间：2026-11-10T17:44:38.239Z
软件包许可：Apache-2\.0

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40convex-dev/sharded-counter
原文对照：https://npmcn.com/package/%40convex-dev/sharded-counter/?lang=original
项目主页：https://github.com/get-convex/sharded-counter#readme
源码仓库：https://github.com/get-convex/sharded-counter

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：107 kB，45 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：convex ^1\.25\.4
- 首次发布：2024-10-16T22:14:25.563Z
- 最新版本发布：2026-10-10T00:52:35.305Z
- 近 30 天下载量：465782（2026-10-11 至 2026-11-09，npm 官方下载统计）
- 已发布版本数：12（近 12 个月 4 个）

## 中文简介

Convex的硬化计数器组件.

## 安装

```sh
npm install @convex-dev/sharded-counter
```

也可以使用：`pnpm add @convex-dev/sharded-counter`、`yarn add @convex-dev/sharded-counter`、`bun add @convex-dev/sharded-counter`

## README

# Convex 硬化柜台组件

[![npm version](https://badge.fury.io/js/@convex-dev%2Fsharded-counter.svg)](https://badge.fury.io/js/@convex-dev%2Fsharded-counter)

此组件为 Convex 添加了计数器. 它扮演着从字符串来的密钥价值商店 改为数字,在更新值时会硬化以增加通量.

由于它是建立在 Convex上, 一切都是自动一致,反应, 并缓存。 因为它的建造与 [构成部分](https://convex.dev/components), (中文(简体) ), 操作是孤立的,即使运行在 平行.

例如,如果想要显示 [100万个复选框](https://en.wikipedia.org/wiki/One_Million_Checkboxes) [在您的 Convex 网站上](https://www.youtube.com/watch?v=LRUWplYoejQ)时,你想 实时计数复选框,同时允许许多框更改 平行.

更一般地说,每当你有一个柜台 经常改变,你可以 使用此组件以有效跟踪.

```ts
export const checkBox = mutation({
  args: { i: v.number() },
  handler: async (ctx, args) => {
    const checkbox = await ctx.db
      .query("checkboxes")
      .withIndex("i", (q) => q.eq("i", args.i))
      .unique();
    if (!checkbox.isChecked) {
      await ctx.db.patch(checkbox._id, { isChecked: true });

      // Here we increment the number of checkboxes.
      await numCheckboxes.inc(ctx);
    }
  },
});
export const getCount = query({
  args: {},
  handler: async (ctx, _args) => {
    return await numCheckboxes.count(ctx);
  },
});
```

这取决于你需要经常修改计数器的假设, 但只需从查询中读取其值,或者在突变中不经常读取. 若为 你每次修改时都会读取计数, 你就会失去硬化的好处.

## 预先要求: Convex

你需要一个现有的 Convex 项目来使用组件。 Convex 是一个主机 后端平台,包括数据库、无服务器功能和多一个吨 可以学习 [这里](https://docs.convex.dev/get-started)。 。 。 .

运行 `npm create convex` 或遵循其中任何一条 [快速启动](https://docs.convex.dev/home) 来设置一个.

## 安装

首先,安装组件包:

```ts
npm install @convex-dev/sharded-counter
```

然后,创建一个 `convex.config.ts` 应用程序中的文件 `convex/` 文件夹和 通过调用安装组件 `use`数字 :

```ts
// convex/convex.config.ts
import { defineApp } from "convex/server";
import shardedCounter from "@convex-dev/sharded-counter/convex.config.js";

const app = defineApp();
app.use(shardedCounter);

export default app;
```

最后,创建一个新的 `ShardedCounter` 在您内部 `convex/` 文件夹和点 转到已安装的组件.

```ts
import { components } from "./_generated/api";
import { ShardedCounter } from "@convex-dev/sharded-counter";

const counter = new ShardedCounter(components.shardedCounter);
```

## 更新和阅读计数器

一旦你有一个 `ShardedCounter`,有几种方法可以用来更新 在变异或动作中键的计数器.

```ts
await counter.add(ctx, "checkboxes", 5); // increment by 5
await counter.inc(ctx, "checkboxes"); // increment by 1
await counter.subtract(ctx, "checkboxes", 5); // decrement by 5
await counter.dec(ctx, "checkboxes"); // decrement by 1
await counter.reset(ctx, "checkboxes"); // reset to 0

const numCheckboxes = counter.for("checkboxes");
await numCheckboxes.inc(ctx); // increment
await numCheckboxes.dec(ctx); // decrement
await numCheckboxes.add(ctx, 5); // add 5
await numCheckboxes.subtract(ctx, 5); // subtract 5
await numCheckboxes.reset(ctx); // reset to 0
```

你可以在查询、变异或动作中读取计数器的价值.

```ts
await counter.count(ctx, "checkboxes");
await numCheckboxes.count(ctx);
```

更多实例使用 [实例.ts](https://npmcn.com/package/%40convex-dev/sharded-counter/example/convex/example.ts)。 。 。 .

## 压倒柜台

当单一文档同时被两个变异修改时 变异缓慢实现 [可序列结果](https://docs.convex.dev/database/advanced/occ)。 。 。 .

为了实现高吞吐量,ShardedCounter将计数分配到 多个文件,称为"硬". 增减 随机更新 shard,而总数的查询则从所有shards读取.

1.  当增量或减量时, 更多的硬块 更大的吞吐量.
2.  查询计数时, 较慢的shards QQ 更耐久 .

您可以在初始化 ShardedCounter 时设置硬体数 专门为每个密钥设置 :

```ts
const counter = new ShardedCounter(components.shardedCounter, {
  shards: { checkboxes: 100 }, // 100 shards for the key "checkboxes"
});
```

或者通过设置一个适用于未在 `shards`数字 :

```ts
const counter = new ShardedCounter(components.shardedCounter, {
  shards: { checkboxes: 100 },
  defaultShards: 8,
});
```

如果没有指定硬币的默认数为16.

注意您的密钥可以是字符串的子类型 。 例如,如果您想要存储一个数 每个用户的朋友, 而你不在乎通过量 对于一个用户, 你会这样宣布ShardedCounter:

```ts
const friendCounts = new ShardedCounter<Id<"users">>(
  components.shardedCounter,
  { defaultShards: 1 },
);

// Decrement a user's friend count by 1
await friendsCount.dec(ctx, userId);
```

## 在读取时减少争议

读取计数符 `counter.count(ctx, "checkboxes")` 读取所有硬体 以获得准确的计数。 这需要读取对所有硬文档的依赖.

-   在查询订阅中,这意味着对计数器的任何更改都会引起查询 重新运行.
-   在变异中,这意味着对计数器的任何修改都会导致 [OCC 操作控制中心](https://docs.convex.dev/error#1) 冲突.

您可以通过估计计数来减小争议:从较小的数中读取 硬度和推论基于硬度的总数.

```ts
const estimatedCheckboxCount = await counter.estimateCount(ctx, "checkboxes");
```

默认情况下,它来自一个单随机的硬度和乘以总数 要构成估计数的硬点数。 你可以通过阅读来改进估计 以更多争议为代价:

```ts
const estimateFromThree = await counter.estimateCount(ctx, "checkboxes", 3);
```

如果柜台是从很多小堆积起来的 `counter.inc` 财务报告和审定财务报表 `counter.dec` 电话,那么它们应该统一分布 在硬体之间,如此估计 数将准确.

在某些情况下,柜台不会平均分配:

-   如果柜台是少数操作累积的
-   如果有些行动 `counter.add`s 或 (简体中文) `counter.subtract`s 有大块 值,因为每个操作只改变一个硬度
-   如果沙子数量改变

在这种情况下,计数可能无法平均地分布在硬盘上. 改为: 您可拨打:

```ts
await counter.rebalance(ctx, "checkboxes");
```

连数数都算不上.

您可以更改第二个参数, 更改一个密钥的硬度数 页:1 `ShardedCounter` 建筑师。 如果你减少硬块的数量,你 将留下额外的硬块,这些硬块不会被写到,但仍被读取 计算 `count`。在这种情况下,你应该打电话 `counter.rebalance` 删除 外相的硬块.

注: `counter.rebalance` 读和写所有的shards, 这样可以引起更多的 OCCs,它被推荐为 节制,从Convex仪表板或 从不常见的克伦.

注:计数为浮点数,而浮点算术并非无限精确. 即使你总是加减整数, 你可能会得到一个分数, 特别是如果你使用 `estimateCount` 或者说 `rebalance`. 分布在各地的价值 硬体可以以不同的组合添加 [浮点算术不是关联](https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html)。 。 。 . 你用得着 `Math.round` 如果需要,可确保您的最终数是整数.

## 计算表格中的文档

您通常想要使用一个被打磨的计数器来跟踪文档中有多少 页:1.

> 如果你想要的不只是一个数, 看一下 [合计部分](https://www.npmjs.com/package/@convex-dev/aggregate)。 。 。 .

有三种方法可以保持一个计数和表同步:

1.  在插入或 从表格中删除.
2.  \[建议\] 将全部写入单独的 TypeScript 函数中的表格, 并总是将这些函数从变异调取出而不是写到 db 直接说 建议采用这种方法,因为它概括了逻辑 更新表格,同时保持所有操作清晰。 譬如说,

```ts
// Example of a mutation that calls `insertUser`.
export const insertPair = mutation(async (ctx) => {
  ...
  await insertUser(ctx, user1);
  await insertUser(ctx, user2);
});

// All inserts to the "users" table go through this function.
async function insertUser(ctx, user) {
  await ctx.db.insert("users", user);
  await counter.inc(ctx, "users");
}
```

3.  登记a [触发](https://www.npmjs.com/package/convex-helpers#triggers), (中文(简体) ), 当一个突变改变表格中的数据时,它自动运行代码.

```ts
// Triggers hook up writes to the table to the ShardedCounter.
const triggers = new Triggers<DataModel>();
triggers.register("mytable", counter.trigger("mycounter"));
export const mutation = customMutation(rawMutation, customCtx(triggers.wrapDB));
```

这个 [插入用户与调试器](https://npmcn.com/package/%40convex-dev/sharded-counter/example/convex/example.ts) 突变使用扳机.

## 返回已存在的计数

如果您想在表格中计数像文档的项目, 您可能已经有 在安装ShardedCounter组件之前,文档,这些组件应该是 记着.

简便的版本是计算一次值并添加该值,如果 还没有主动的请求发生。 您也可以定期重新计算 如果在飞行中没有要求,则更新计数器的价值.

棘手的部分是处理请求时进行计算:确保 将活动更新合并为要返回填充的旧值.

### 简单的后补: 如果表格是附件

Ưμ㼯A [实例/会议/实例](https://npmcn.com/package/%40convex-dev/sharded-counter/example/convex/example.ts)。 。 。 .

步进:

1.  更改现场留言更新计数器. 举个例子,你会 变化 `insertUserBeforeBackfill` 将作为 `insertUserAfterBackfill`。 。 。 .
2.  写入一个回填, 计算代码之前创建的文档 (1) 部署。 举例来说,这将是 `backfillOldUsers`。 。 。 .
3.  运行 `backfillOldUsers` 从仪表板.

### 复杂的回填: 如果文档可能被删除

Ưμ㼯A [实例/会议/实例](https://npmcn.com/package/%40convex-dev/sharded-counter/example/convex/example.ts)。 。 。 .

步进:

1.  创建 `backfillCursor` 以图示显示的表格
2.  在此表格中创建有字段的新文档 `{ creationTime: 0, id: "", isDone: false }`
3.  任何您想要根据文档更改更新一个计数器的地方,请将 以条件更新, 只有在返回填充时才更新 处理该文件。 举个例子,你会改变 `insertUserBeforeBackfill` 将作为 `insertUserDuringBackfill`。 。 。 .
4.  定义类似于 `backfillUsers` 财务报告和审定财务报表 `backfillUsersBatch`
5.  打电话 `backfillUsersBatch` 从仪表板.
6.  删除更新计数器时的条件 。 举个例子,你会 变化 `insertUserDuringBackfill` 将作为 `insertUserAfterBackfill`。 。 。 .
7.  删除 `backfillCursor` 页:1.

## 常见问题

### @convex-dev/sharded-counter 是什么？

Convex的硬化计数器组件\.

### 如何安装 @convex-dev/sharded-counter？

在项目目录运行 npm install @convex-dev/sharded-counter，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：convex（^1\.25\.4）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @convex-dev/sharded-counter 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @convex-dev/sharded-counter 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @convex-dev/sharded-counter 可以商用吗？

@convex-dev/sharded-counter 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @convex-dev/sharded-counter 的下载量有多少？

根据 npm 官方下载统计，@convex-dev/sharded-counter 在 2026/10/11 – 2026/11/09 这 30 天内被下载 465,782 次，日均约 15,526 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @convex-dev/sharded-counter 还在维护吗？

最新版本 0\.2\.3 发布于 2026/10/10（1 个月前）；至今共发布 12 个版本，其中过去 12 个月发布了 4 个；首次发布于 2024/10/17。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

