如何获取所有 IDBIndex 键值(而不是对象存储主键)?

How to get all IDBIndex key values (instead of object store primary keys)?

我有一个带有主键和附加索引(带有唯一键约束)的 IndexedDB 对象存储。

现在我想检索该索引的所有键值。

以前,我使用 IDBIndex.getAllKeys(),但显然此方法的行为已更改为 return 对象存储主键而不是索引键。 (但是,我无法在浏览器发行说明中找到任何文档或参考...)

所以我的问题是: 检索所有索引键值的推荐的、最有效的方法是什么?

IDBIndex.getAll 会工作,但它会将所有值读入内存,这可能会很慢。

你说得对 IDBIndex.getAllKeys return 只有主键,没有索引键。

不幸的是,没有类似的单一函数可以 return 索引键,但您可以使用 IDBIndex.openKeyCursor 并避免将值读入内存:

const result = [];

index.openKeyCursor().onsuccess = (event) => {
    var cursor = event.target.result;
    if (cursor) {
        // cursor.key is the index key, cursor.primaryKey is the primary key,
        // and cursor.value is undefined because we're using openKeyCursor
        // rather than openCursor.
        result.push(cursor.key);
        cursor.continue();
    } else {
        cb(result);
    }
};

我还没有对此进行基准测试,但理论上它可能与 getAllKeys 一样快,尽管可能至少慢一些,因为它需要触发和处理 N 个事件而不是一个。

只是不要在 MS Edge 中尝试:)

Previously, I used IDBIndex.getAllKeys(), but appearently the behaviour of this method has changed to return the object store primary keys instead of the index keys. (I cannot, however, find any documentation, or reference in browser release notes to that effect...)

如果您使用的是 indexeddb-getall-shim,早期版本会错误地 return 索引键而不是主键。这从来没有出现在规范中,只是 shim 中的一个错误。因为我写了垫片...如果这确实是你困惑的根源,我很抱歉!

Do you know why there is an IDBIndex.getAllKeys() method if it returns the same thing as IDBObjectStore.getAllKeys()

使用这两种不同方法的一个原因是它们都接受一个可选的 query 参数,这是一个关键范围。

IDBObjectStore.getAllKeys(query)的情况下,键范围是个主键的范围,结果是个主键的数组

IDBIndex.getAllKeys(query)的情况下,键范围是索引键的范围,结果是主键[=的数组29=]

示例:

/* store (key = SSN) */
const users = await db.createObjectStore("users", { keyPath: "SSN" });

/* index (key = surname) */
users.createIndex("surname", "surname");

/* 1. get all SSNs from store */
const keys = await users.getAllKeys();

/* 2. get all SSNs starting between 'a' and 'f' */
const keys = await users.getAllKeys(IDBKeyRange.bound('a', 'f'));

/* 3. get all SSNs from index (same as #1) */
const keys = await users.index("surname").getAllKeys();

/* 4. get all SSNs where surname is between 'a' and 'f' (different to #2) */
const keys = await users.index("surname").getAllKeys(IDBKeyRange.bound('a', 'f'));