Skip to content

IndexedDB - Reading Data

Storing data is only half the story; you need efficient ways to retrieve it. IndexedDB offers several methods for reading data, from fetching a single record to iterating over millions of entries. All read operations should happen in a readonly transaction for best performance.

Here are the primary methods you’ll use, shown with the clean idb library syntax:

  • db.get(storeName, key): Retrieves a single object from storeName by its primary key. Returns undefined if no matching object is found.
  • db.getAll(storeName, [query], [count]): Retrieves all objects from storeName. Optionally, you can provide a key range query to filter results. Very convenient, but be cautious with huge datasets as it loads everything into memory.
  • index.get(key): Retrieves the first object that matches the key from an index.
  • index.getAll(key): Retrieves all objects that match the key from an index.
  • store.openCursor([query]): The most powerful and memory-efficient method. A cursor lets you iterate over records one by one, which is essential for working with large datasets without loading them all into memory at once.

This example sets up a database of employees with an index on their department. It then demonstrates each of the core reading methods to solve different queries.

<!DOCTYPE html>
<html lang="en">
<head>
<title>IndexedDB Reading Data</title>
<script type="module" src="app.js"></script>
</head>
<body>
<h1>Reading Data from IndexedDB</h1>
<p>Check the console for output.</p>
</body>
</html>
// app.js
import { openDB } from 'https://cdn.jsdelivr.net/npm/idb@7/build/esm/index.js';
const DB_NAME = 'CompanyDB';
const STORE_NAME = 'employees';
const DEPT_INDEX = 'department_idx';
async function setupAndQuery() {
const db = await openDB(DB_NAME, 1, {
upgrade(db) {
const store = db.createObjectStore(STORE_NAME, { keyPath: 'id', autoIncrement: true });
store.createIndex(DEPT_INDEX, 'department', { unique: false });
},
});
// Use a transaction to clear existing data and add fresh data
const tx = db.transaction(STORE_NAME, 'readwrite');
await tx.store.clear(); // Clear store for a clean demo run
await Promise.all([
tx.store.add({ name: 'Alice', department: 'Engineering' }),
tx.store.add({ name: 'Bob', department: 'Marketing' }),
tx.store.add({ name: 'Charlie', department: 'Engineering' }),
tx.store.add({ name: 'Diana', department: 'HR' }),
]);
await tx.done;
console.log('Database populated.');
console.log('\n--- Query Examples ---');
// 1. Get a single employee by primary key (e.g., ID 2)
const bob = await db.get(STORE_NAME, 2);
console.log('1. Get by primary key (ID 2):', bob);
// 2. Get all employees
const allEmployees = await db.getAll(STORE_NAME);
console.log('2. Get all employees:', allEmployees);
// 3. Get all employees from the 'Engineering' department using the index
const engineers = await db.getAllFromIndex(STORE_NAME, DEPT_INDEX, 'Engineering');
console.log('3. Get all from index (department = Engineering):', engineers);
// 4. Use a cursor to iterate and log only marketing employees
console.log('4. Using a cursor to find marketing staff:');
let cursorTx = db.transaction(STORE_NAME, 'readonly');
let store = cursorTx.objectStore(STORE_NAME);
for await (const cursor of store.iterate()) {
if (cursor.value.department === 'Marketing') {
console.log(` - Found: ${cursor.value.name}`);
}
}
db.close();
}
setupAndQuery();

If a get() or getAll() operation returns undefined or an empty array when you expect data, check the following:

  • Correct Key/Value: Are you sure the key or index value you’re querying for actually exists? Double-check for typos and case-sensitivity.
  • Transaction Scope: Did you include the correct object store name when you started the transaction?
  • Asynchronous Timing: Ensure you are awaiting the result of your read operation before trying to use it.