IndexedDB - Indexes
IndexedDB - Supercharging Data Retrieval with Indexes
Section titled “IndexedDB - Supercharging Data Retrieval with Indexes”Imagine an object store is like a book. Finding a specific piece of information by reading from start to finish would be slow, especially for a large book. An index is like the index at the back of the book: it provides a fast way to look up information. Instead of scanning the entire store, you can query the index to quickly find the records you need based on a specific property.
Indexes are created on an object store and allow you to fetch data using a property of the stored objects, rather than just their primary key. This is essential for efficient querying.
Creating an Index
Section titled “Creating an Index”Indexes, like object stores, can only be created within a versionchange transaction, which occurs inside the onupgradeneeded event handler when you open a database with a new version number. You use the createIndex() method on an object store instance.
// Inside the onupgradeneeded event handlerconst store = db.createObjectStore('bots', { keyPath: 'id' });const branchIndex = store.createIndex('branch_idx', 'branch', { unique: false });The createIndex method accepts three arguments:
- indexName (string): A unique name for the index within the object store (e.g., ‘branch_idx’).
- keyPath (string | string[]): The property (or properties for a compound index) on your stored objects that the index will use for lookups (e.g., ‘branch’).
- options (object, optional): An object to configure the index’s behavior:
- unique (boolean): If
true, the database enforces that no two objects can have the same value for the indexed property. Defaults tofalse. - multiEntry (boolean): If the
keyPathpoints to an array, settingmultiEntry: truecreates an index entry for each element in the array. This is powerful for implementing tags or categories. Defaults tofalse.
Example: Creating and Querying an Index
Section titled “Example: Creating and Querying an Index”This example demonstrates creating a database, adding an index, populating it with data, and then using the index to efficiently retrieve specific records. We’ll use a modern async/await structure for cleaner code. Notice we’re not using document.write; instead, we log results to the browser’s developer console, which is standard practice.
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>IndexedDB Indexes Example</title></head><body> <h1>IndexedDB Indexes Example</h1> <p>Check the browser's developer console for output.</p>
<script> const DB_NAME = 'BotDatabase'; const DB_VERSION = 1; const STORE_NAME = 'bots'; const BRANCH_INDEX = 'branch_idx';
async function runDemo() { // 1. Open the database connection const request = indexedDB.open(DB_NAME, DB_VERSION);
request.onerror = (event) => { console.error(`Database error: ${event.target.error}`); };
request.onupgradeneeded = (event) => { const db = event.target.result; console.log('Running onupgradeneeded...');
// Create an object store if it doesn't exist if (!db.objectStoreNames.contains(STORE_NAME)) { const store = db.createObjectStore(STORE_NAME, { keyPath: 'id' }); // Create an index on the 'branch' property store.createIndex(BRANCH_INDEX, 'branch', { unique: false }); console.log('Object store and index created.'); } };
request.onsuccess = async (event) => { const db = event.target.result; console.log('Database opened successfully.');
try { // 2. Populate data in a 'readwrite' transaction const txWrite = db.transaction(STORE_NAME, 'readwrite'); const storeWrite = txWrite.objectStore(STORE_NAME);
const bots = [ { id: 1, name: 'Jason', branch: 'IT' }, { id: 2, name: 'Praneeth', branch: 'CSE' }, { id: 3, name: 'Palli', branch: 'EEE' }, { id: 4, name: 'Abdul', branch: 'IT' }, { id: 5, name: 'Deevana', branch: 'CSE' }, ];
// Use Promise.all to wait for all 'put' operations to complete await Promise.all(bots.map(bot => storeWrite.put(bot))); console.log('Data populated.'); await txWrite.done; // Wait for the transaction to complete
// 3. Query data using the index in a 'readonly' transaction const txRead = db.transaction(STORE_NAME, 'readonly'); const storeRead = txRead.objectStore(STORE_NAME); const branchIndex = storeRead.index(BRANCH_INDEX);
// Get all bots in the 'IT' branch const itBotsRequest = branchIndex.getAll('IT'); itBotsRequest.onsuccess = () => { console.log("Query Result: All bots in 'IT' branch:", itBotsRequest.result); };
// Get a single bot from the 'EEE' branch const eeeBotRequest = branchIndex.get('EEE'); eeeBotRequest.onsuccess = () => { console.log("Query Result: A single bot from 'EEE' branch:", eeeBotRequest.result); };
await txRead.done;
} catch (err) { console.error('An error occurred during transactions:', err); } finally { // 4. Close the database connection db.close(); console.log('Database connection closed.'); } }; }
runDemo(); </script></body></html>Expected Console Output
Section titled “Expected Console Output”When you run the above HTML file, open your browser’s developer console. You should see output similar to this:
Running onupgradeneeded...Object store and index created.Database opened successfully.Data populated.Query Result: All bots in 'IT' branch:[ { id: 1, name: 'Jason', branch: 'IT' }, { id: 4, name: 'Abdul', branch: 'IT' }]Query Result: A single bot from 'EEE' branch:{ id: 3, name: 'Palli', branch: 'EEE' }Database connection closed.