indexeddb 的 keypath 和 autoincrement 共同控制主键行为:keypath 指定对象属性路径作为主键,要求字段存在且唯一;autoincrement 在无 keypath 或 keypath 为 null 时启用,自动生成递增数字主键;二者可组合使用,如 keypath: "id" + autoincrement 实现有无 id 均支持。

IndexedDB 的键路径(keyPath)和键生成器(keyGenerator)是控制数据主键行为的两个核心配置,它们决定每条记录如何获得唯一标识,直接影响插入、查询和更新逻辑。
keyPath:用对象属性作为主键
keyPath 是一个字符串,指定对象中哪个属性作为主键。它必须是合法的 JavaScript 标识符路径(如 "id" 或 "user.profile.name"),不支持特殊字符(如 @、&、- 等),因为底层解析机制依赖点号分隔的属性访问语法。
- 设为 "id":插入对象时必须包含 id 属性,且值不能重复,否则 add() 报
ConstraintError - 设为 "id" 但没提供 id:调用 add() 会失败;put() 可覆盖,但需显式传入完整对象
- 嵌套路径如 "meta.createdAt":要求对象结构为
{ meta: { createdAt: "2026-06-15" } },否则取值为 undefined,导致主键无效
keyGenerator:让系统自动生成主键
keyGenerator 不是独立配置项,而是通过 autoIncrement: true 启用的机制。它只在未指定 keyPath 或 keyPath 为 null 时生效,由 IndexedDB 自动分配递增数字(从 1 开始)作为主键。
- 创建 store 时写
{ autoIncrement: true }:主键由系统生成,不存入对象本身,读取时可通过 event.target.result.key 获取 - 同时设 keyPath: "id" 和 autoIncrement: true:id 字段被当作主键,且自动递增——此时插入对象可省略 id,数据库会补上并确保唯一
- 仅设 autoIncrement: true 而不设 keyPath:主键是纯数字,对象里不会出现该字段,适合不需要业务含义 ID 的场景(如日志流水号)
keyPath 与 autoIncrement 的组合效果
二者不是互斥关系,而是协同工作。关键看你怎么声明对象仓库:
-
createObjectStore("logs", { keyPath: "id", autoIncrement: true })→ 插入时若无 id,自动生成;若有,则用你给的值(需保证唯一) -
createObjectStore("notes", { autoIncrement: true })→ 主键始终是数字,对象无需含任何 ID 字段 -
createObjectStore("users", { keyPath: "email" })→ email 必须存在且唯一,系统不生成,也不递增
常见陷阱与应对建议
实际开发中容易踩坑的地方集中在 keyPath 的合法性与数据预处理上:
- 后端返回字段含 @(如
"user@domain.com"):不能直接用作 keyPath,应预处理为 "userAtDomainCom" 或提取为标准字段(如 "email") - 想用数组索引或动态键名:IndexedDB 不支持,需在存入前转换结构,例如把
{ "tag@v1": "active" }改成{ tagV1: "active" } - 升级数据库时修改 keyPath:必须在 onupgradeneeded 中重建 objectStore,旧数据不会自动迁移,需手动导出再导入











