Token导航 LogoToken导航TokenDH.com
待分类需要联网github未标认证来源可访问许可证需确认审计提醒

convex-aggregate凸聚合体

Agent Skill

convex-aggregate 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

21

周安装

17

GitHub Stars

1

下载量

140
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

2

许可证

unknown

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:convex-aggregate(凸聚合体)
来源仓库:https://github.com/imfa-solutions/skills
仓库路径:skills/convex-aggregate
安装命令:
npx skills add https://github.com/imfa-solutions/skills --skill convex-aggregate
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/imfa-solutions/skills --skill convex-aggregate

简介

提供高效的聚合操作,支持 O(log n) 复杂度的计数、求和、排名和分页查询。

  • 适用于大规模数据统计、排行榜生成和高效偏移访问等性能敏感场景。
  • 基于去规范化 B-tree 结构实现,需正确配置索引名称和字段顺序。
  • 使用前应检查是否已安装 @convex-dev/aggregate 包并正确注册到 Convex 应用。
  • convex-aggregate 属于待分类类 Skill,可作为该场景下的辅助能力补充。

SKILL.md

Convex Aggregate — O(log n) Count, Sum, Rank & Pagination

@convex-dev/aggregate — Efficient aggregation via denormalized B-tree. O(log n) for count, sum, min, max, rank, offset access, and percentiles.

Installation & Setup

npm install @convex-dev/aggregate
// convex/convex.config.ts
import { defineApp } from "convex/server";
import aggregate from "@convex-dev/aggregate/convex.config.js";

const app = defineApp();
app.use(aggregate);
// Multiple aggregates:
// app.use(aggregate, { name: "byScore" });
// app.use(aggregate, { name: "byUser" });
export default app;

Run npx convex dev to generate the component API.

Core Concepts

TableAggregate vs DirectAggregate

TableAggregateDirectAggregate
Tied toA Convex tableNothing (standalone)
SyncDerives keys from doc fieldsManual insert/delete/replace
Best forTable data with auto-syncAnalytics, metrics, non-table data
ConstructorsortKey, sumValue, namespace fnsJust type params

Keys

Sort keys determine ordering. Can be: number, string, null, or tuples ([string, number]).

Critical: Sort order follows key structure:

// Key: [game, score] → max({ prefix: [game] }) returns highest SCORE for that game
// Key: [game, username] → max({ prefix: [game] }) returns highest USERNAME, not score!

Namespaces

Partition data into separate B-trees. Each namespace is isolated — no contention between them, but no cross-namespace aggregation.

Use when: data is naturally partitioned (games, albums, orgs) AND you don't need global aggregates.

Bounds

Limit query range — reduces read dependencies and write contention:

// Range
{ bounds: { lower: { key: 65, inclusive: false }, upper: { key: 100, inclusive: true } } }
// Prefix (for tuple keys)
{ bounds: { prefix: [gameId, username] } }
// Exact match
{ bounds: { eq: specificKey } }

TableAggregate Setup

import { TableAggregate } from "@convex-dev/aggregate";
import { components } from "./_generated/api";
import type { DataModel } from "./_generated/dataModel";

const aggregate = new TableAggregate<{
  Key: number;                    // Sort key type
  DataModel: DataModel;
  TableName: "scores";
  Namespace?: string;             // Optional
}>(components.aggregate, {
  sortKey: (doc) => doc.score,    // REQUIRED: extract sort key
  sumValue: (doc) => doc.score,   // Optional: value for sum()
  namespace: (doc) => doc.gameId, // Optional: partition key
});

DirectAggregate Setup

import { DirectAggregate } from "@convex-dev/aggregate";

const aggregate = new DirectAggregate<{
  Key: number;
  Id: string;
  Namespace?: string;
}>(components.aggregate);

Query Methods (both TableAggregate & DirectAggregate)

// Count (all or bounded)
await aggregate.count(ctx);
await aggregate.count(ctx, { bounds: { prefix: [gameId] }, namespace: "ns" });

// Sum (requires sumValue)
await aggregate.sum(ctx);
await aggregate.sum(ctx, { bounds: { lower: { key: 0, inclusive: true } } });

// Offset access (0-indexed, supports negative)
await aggregate.at(ctx, 0);       // first
await aggregate.at(ctx, -1);      // last
await aggregate.at(ctx, 99, { namespace: "album1" });

// Rank (how many items before this key)
await aggregate.indexOf(ctx, 95);
await aggregate.indexOf(ctx, score, { order: "desc" });

// Min / Max → { key, id, sumValue } | null
await aggregate.min(ctx, { bounds: { prefix: [gameId] } });
await aggregate.max(ctx, { namespace: "game1" });

// Random (uniform)
await aggregate.random(ctx);

// Paginate
const { page, cursor, isDone } = await aggregate.paginate(ctx, {
  cursor: undefined, order: "asc", pageSize: 100,
  bounds: { prefix: [gameId] },
});

// Async iterator
for await (const item of aggregate.iter(ctx, { order: "desc", pageSize: 50 })) {
  // item: { key, id, sumValue }
}

Write Methods

TableAggregate writes (call after db operations)

// After db.insert
const id = await ctx.db.insert("scores", data);
const doc = await ctx.db.get(id);
await aggregate.insert(ctx, doc!);

// After db.delete
await aggregate.delete(ctx, doc);

// After db.patch / db.replace
await aggregate.replace(ctx, oldDoc, newDoc);

// Idempotent versions (for migrations/backfills):
await aggregate.insertIfDoesNotExist(ctx, doc);
await aggregate.deleteIfExists(ctx, doc);
await aggregate.replaceOrInsert(ctx, oldDoc, newDoc);

// Document ranking
const rank = await aggregate.indexOfDoc(ctx, doc, { order: "asc" });

DirectAggregate writes

await aggregate.insert(ctx, { key: 95, id: "unique-id", sumValue: 95 });
await aggregate.delete(ctx, { key: 95, id: "unique-id" });
await aggregate.replace(ctx, { key: 95, id: "unique-id" }, { key: 100, sumValue: 100 });
// Same idempotent variants available

Clear / reinitialize

await aggregate.clear(ctx);
await aggregate.clear(ctx, { maxNodeSize: 32, rootLazy: false, namespace: "ns" });
await aggregate.clearAll(ctx); // all namespaces
await aggregate.makeRootLazy(ctx); // convert eager root to lazy

Keeping Data in Sync

CRITICAL: Always update the aggregate when modifying the source table.

Approach 1: Encapsulated helpers (recommended)

async function insertScore(ctx, args) {
  const id = await ctx.db.insert("scores", args);
  const doc = await ctx.db.get(id);
  await aggregate.insert(ctx, doc!);
  return id;
}

Approach 2: Triggers (convex-helpers)

import { Triggers } from "convex-helpers/server/triggers";
import { customCtx, customMutation } from "convex-helpers/server/customFunctions";

const triggers = new Triggers<DataModel>();
triggers.register("scores", aggregate.trigger());

const mutationWithTriggers = customMutation(rawMutation, customCtx(triggers.wrapDB));

export const addScore = mutationWithTriggers({
  handler: async (ctx, args) => {
    return await ctx.db.insert("scores", args); // aggregate updates via trigger
  },
});

Key Design Rules

GoalKey designWhy
Highest score per game[gameId, score]max({prefix: [gameId]}) returns max score
User-specific stats[username, score]prefix: [username] filters to one user
Time-based queries_creationTimeNatural ordering for ranges
Simple count / randomnullNo ordering needed

Avoid: [game, username] if you want max *score* — max returns highest *username* alphabetically.

Best Practices Summary

PracticeRationale
Always use bounds when possibleReduces read dependencies and write contention
Use namespaces for partitioned dataEliminates cross-partition contention
Use batch operations for multiple queriesSignificantly more efficient than individual calls
Use encapsulated helpers or triggersPrevents aggregate from going out of sync
Use insertIfDoesNotExist during backfillsIdempotent — safe to rerun
Use lazy root (default) for write-heavySpreads writes across tree
Set rootLazy: false for read-heavyFaster reads at cost of write contention

Reference Files

  • Full examples: Leaderboard, offset pagination, random access, user aggregations, analytics → See references/examples.md
  • Advanced topics: Batch ops, performance/contention optimization, troubleshooting, migrations, type definitions → See references/advanced.md

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

36.92%
按下载量换算52

Claude

29.15%
按下载量换算41

Cursor

19.12%
按下载量换算27

Gemini CLI

10.27%
按下载量换算14

安全审计

Gen Agent Trust Hub

通过

Socket

可疑

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。当前只有一个来源,正式发布前建议补源仓库或其他目录站核验。

来源信息

继续浏览同类 Skills