有索引,为何查询不了数据呢?

indexedDB的一条数据如下:

{isSelected: false, projName: '222', desc: '222', path: '/Users/jphn/electron-code/src', create_time: '2025-03-15T03:03:06.805Z', …}

image.png

定义时候:是有给isSelected的索引的:

db.version(1).stores({
  settings: '++id',
  projs: '++id,name,desc,path,isSelected'
})

我查询的时候:

const selectedProj = await db.projs.where('isSelected').equals(true).first();

报错:

projApi.dexie.ts:42 Unable to get selected project: 
DexieError2 {name: 'DataError', message: "Failed to execute 'bound' on 'IDBKeyRange': The pa… 'IDBKeyRange': The parameter is not a valid key.", inner: DataError: Failed to execute 'bound' on 'IDBKeyRange': The parameter is not a valid key.
    at mak…}
阅读 467
avatarAI BotBETA

出现此问题的根本原因是:IndexedDB 的索引键不允许使用 boolean 类型值。在 IndexedDB 规范中,合法的键类型包括:string、number、Date、Array(由这些类型组成),但不包含 boolean 类型。

具体解决方法:

  1. 修改数据库 Schema

    // 将索引字段转换为数值类型 (0/1)
    db.version(1).stores({
      settings: '++id',
      projs: '++id,name,desc,path,isSelected'
    });
  2. 存储数据时转换类型

    // 存入时转换 boolean 为 number (true → 1, false → 0)
    await db.projs.add({
      ...yourData,
      isSelected: 1 // 或 0
    });
  3. 修改查询方式

    // 查询时使用 1 替代 true
    const selectedProj = await db.projs.where('isSelected').equals(1).first();

额外注意事项:

  • 需要将现有数据中的 isSelected 字段批量转换为数值类型 (0/1)
  • 如果之前已有旧版本数据库,需通过 db.delete() 删除旧库或增加版本号触发升级
  • 使用 Dexie 的 mapToClass 可以在模型层自动处理类型转换

错误原理说明:
当试图用 true 作为索引键值查询时,IndexedDB 底层会检测到键类型不合法 (boolean 不是有效的键类型),从而抛出 DataError。该错误会沿着 Dexie 的 Promise 链向上传播,最终被你的 try/catch 捕获。

1 个回答
  1. 某些版本的浏览器在IndexedDB中不支持布尔值作为键

将布尔值转换为数字或字符串:

// 在存储数据时
const projData = {
  projName: '222',
  desc: '222',
  path: '/Users/jphn/electron-code/src',
  isSelected: 1,  // 使用0和1代替false和true
  create_time: '2025-03-15T03:03:06.805Z'
};

// 或者作为字符串
const projData = {
  // ...其他字段
  isSelected: 'true',  // 使用'false'和'true'字符串
};

// 在查询时
const selectedProj = await db.projs.where('isSelected').equals(1).first();
// 或
const selectedProj = await db.projs.where('isSelected').equals('true').first();

将布尔值以数字形式存储(0表示false,1表示true),这是最简单且兼容性最好的方式。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题