0
# Object Store Operations
1
2
Enhanced object store interface with promise-based operations and async iteration support.
3
4
## Capabilities
5
6
### Store Properties
7
8
Access object store metadata and transaction information.
9
10
```typescript { .api }
11
/**
12
* The names of indexes in the store
13
*/
14
readonly indexNames: TypedDOMStringList<IndexNames<DBTypes, StoreName>>;
15
16
/**
17
* The associated transaction
18
*/
19
readonly transaction: IDBPTransaction<DBTypes, TxStores, Mode>;
20
```
21
22
**Usage Examples:**
23
24
```typescript
25
const tx = db.transaction("users", "readwrite");
26
const userStore = tx.store;
27
28
// Check available indexes
29
console.log("Available indexes:", [...userStore.indexNames]);
30
31
// Access parent transaction
32
console.log("Transaction mode:", userStore.transaction.mode);
33
34
// Check if specific index exists
35
if (userStore.indexNames.contains("email")) {
36
const emailIndex = userStore.index("email");
37
const userByEmail = await emailIndex.get("alice@example.com");
38
}
39
```
40
41
### Data Modification Operations
42
43
Add, update, and delete records in the object store.
44
45
#### Add Operation
46
47
```typescript { .api }
48
/**
49
* Add a value to the store
50
* Rejects if an item of a given key already exists in the store
51
* Only available in readwrite and versionchange transactions
52
* @param value - Value to add to the store
53
* @param key - Optional key (if not using keyPath)
54
* @returns Promise resolving to the key of the added item
55
*/
56
add: Mode extends 'readonly'
57
? undefined
58
: (
59
value: StoreValue<DBTypes, StoreName>,
60
key?: StoreKey<DBTypes, StoreName> | IDBKeyRange
61
) => Promise<StoreKey<DBTypes, StoreName>>;
62
```
63
64
#### Put Operation
65
66
```typescript { .api }
67
/**
68
* Put an item in the store
69
* Replaces any item with the same key
70
* Only available in readwrite and versionchange transactions
71
* @param value - Value to put in the store
72
* @param key - Optional key (if not using keyPath)
73
* @returns Promise resolving to the key of the stored item
74
*/
75
put: Mode extends 'readonly'
76
? undefined
77
: (
78
value: StoreValue<DBTypes, StoreName>,
79
key?: StoreKey<DBTypes, StoreName> | IDBKeyRange
80
) => Promise<StoreKey<DBTypes, StoreName>>;
81
```
82
83
#### Delete Operation
84
85
```typescript { .api }
86
/**
87
* Deletes records in store matching the given query
88
* Only available in readwrite and versionchange transactions
89
* @param key - Key or key range to delete
90
* @returns Promise that resolves when deletion is complete
91
*/
92
delete: Mode extends 'readonly'
93
? undefined
94
: (key: StoreKey<DBTypes, StoreName> | IDBKeyRange) => Promise<void>;
95
```
96
97
#### Clear Operation
98
99
```typescript { .api }
100
/**
101
* Deletes all records in store
102
* Only available in readwrite and versionchange transactions
103
* @returns Promise that resolves when clearing is complete
104
*/
105
clear: Mode extends 'readonly' ? undefined : () => Promise<void>;
106
```
107
108
**Data Modification Examples:**
109
110
```typescript
111
// Write operations (readwrite transaction required)
112
const tx = db.transaction("users", "readwrite");
113
const userStore = tx.store;
114
115
// Add new records (fails if key exists)
116
const userId1 = await userStore.add({ name: "Alice", email: "alice@example.com" });
117
const userId2 = await userStore.add({ name: "Bob", email: "bob@example.com" });
118
119
// Put records (replaces if key exists)
120
await userStore.put({ id: userId1, name: "Alice Smith", email: "alice@example.com" });
121
122
// Delete specific record
123
await userStore.delete(userId2);
124
125
// Delete multiple records with key range
126
await userStore.delete(IDBKeyRange.bound(100, 200));
127
128
// Clear all records
129
await userStore.clear();
130
131
await tx.done;
132
133
// Read operations (readonly transaction is sufficient)
134
const readTx = db.transaction("users", "readonly");
135
const readStore = readTx.store;
136
137
// These operations are not available in readonly mode:
138
// readStore.add - undefined
139
// readStore.put - undefined
140
// readStore.delete - undefined
141
// readStore.clear - undefined
142
```
143
144
### Data Retrieval Operations
145
146
Query and retrieve records from the object store.
147
148
#### Get Operations
149
150
```typescript { .api }
151
/**
152
* Retrieves the value of the first record matching the query
153
* Resolves with undefined if no match is found
154
* @param query - Key or key range to match
155
* @returns Promise resolving to the value or undefined
156
*/
157
get(
158
query: StoreKey<DBTypes, StoreName> | IDBKeyRange
159
): Promise<StoreValue<DBTypes, StoreName> | undefined>;
160
161
/**
162
* Retrieves all values that match the query
163
* @param query - Key or key range to match (optional)
164
* @param count - Maximum number of values to return (optional)
165
* @returns Promise resolving to array of matching values
166
*/
167
getAll(
168
query?: StoreKey<DBTypes, StoreName> | IDBKeyRange | null,
169
count?: number
170
): Promise<StoreValue<DBTypes, StoreName>[]>;
171
```
172
173
#### Key Operations
174
175
```typescript { .api }
176
/**
177
* Retrieves the key of the first record that matches the query
178
* Resolves with undefined if no match is found
179
* @param query - Key or key range to match
180
* @returns Promise resolving to the key or undefined
181
*/
182
getKey(
183
query: StoreKey<DBTypes, StoreName> | IDBKeyRange
184
): Promise<StoreKey<DBTypes, StoreName> | undefined>;
185
186
/**
187
* Retrieves the keys of records matching the query
188
* @param query - Key or key range to match (optional)
189
* @param count - Maximum number of keys to return (optional)
190
* @returns Promise resolving to array of matching keys
191
*/
192
getAllKeys(
193
query?: StoreKey<DBTypes, StoreName> | IDBKeyRange | null,
194
count?: number
195
): Promise<StoreKey<DBTypes, StoreName>[]>;
196
```
197
198
#### Count Operation
199
200
```typescript { .api }
201
/**
202
* Retrieves the number of records matching the given query
203
* @param key - Key or key range to count (optional)
204
* @returns Promise resolving to the count
205
*/
206
count(
207
key?: StoreKey<DBTypes, StoreName> | IDBKeyRange | null
208
): Promise<number>;
209
```
210
211
**Data Retrieval Examples:**
212
213
```typescript
214
const tx = db.transaction("users", "readonly");
215
const userStore = tx.store;
216
217
// Get single record by key
218
const user = await userStore.get("user123");
219
if (user) {
220
console.log("Found user:", user.name);
221
}
222
223
// Get multiple records
224
const allUsers = await userStore.getAll();
225
const recentUsers = await userStore.getAll(IDBKeyRange.lowerBound(1000));
226
const firstTenUsers = await userStore.getAll(null, 10);
227
228
// Get keys only (more efficient when you don't need values)
229
const allUserKeys = await userStore.getAllKeys();
230
const recentUserKeys = await userStore.getAllKeys(IDBKeyRange.lowerBound(1000), 50);
231
232
// Get specific key
233
const foundKey = await userStore.getKey(IDBKeyRange.bound("user100", "user200"));
234
235
// Count records
236
const totalUsers = await userStore.count();
237
const activeUsers = await userStore.count(IDBKeyRange.only("active"));
238
239
await tx.done;
240
```
241
242
### Index Management
243
244
Create and access indexes during database upgrades.
245
246
```typescript { .api }
247
/**
248
* Creates a new index in store
249
* Throws "InvalidStateError" if not called within an upgrade transaction
250
* Only available in versionchange transactions
251
* @param name - Name of the index
252
* @param keyPath - Property path or array of paths for the index
253
* @param options - Index configuration options
254
* @returns Enhanced index interface
255
*/
256
createIndex: Mode extends 'versionchange'
257
? <IndexName extends IndexNames<DBTypes, StoreName>>(
258
name: IndexName,
259
keyPath: string | string[],
260
options?: IDBIndexParameters
261
) => IDBPIndex<DBTypes, TxStores, StoreName, IndexName, Mode>
262
: undefined;
263
264
/**
265
* Get an index by name
266
* @param name - Name of the index
267
* @returns Enhanced index interface
268
*/
269
index<IndexName extends IndexNames<DBTypes, StoreName>>(
270
name: IndexName
271
): IDBPIndex<DBTypes, TxStores, StoreName, IndexName, Mode>;
272
```
273
274
**Index Management Examples:**
275
276
```typescript
277
// Creating indexes during database upgrade
278
const db = await openDB("my-database", 2, {
279
upgrade(db, oldVersion) {
280
if (oldVersion < 1) {
281
const userStore = db.createObjectStore("users", {
282
keyPath: "id",
283
autoIncrement: true
284
});
285
286
// Create various types of indexes
287
userStore.createIndex("email", "email", { unique: true });
288
userStore.createIndex("name", "name");
289
userStore.createIndex("age", "age");
290
userStore.createIndex("fullName", ["firstName", "lastName"]);
291
userStore.createIndex("tags", "tags", { multiEntry: true });
292
}
293
}
294
});
295
296
// Using indexes for queries
297
const tx = db.transaction("users", "readonly");
298
const userStore = tx.store;
299
300
// Access specific indexes
301
const emailIndex = userStore.index("email");
302
const nameIndex = userStore.index("name");
303
const ageIndex = userStore.index("age");
304
305
// Query using indexes
306
const userByEmail = await emailIndex.get("alice@example.com");
307
const usersByName = await nameIndex.getAll("Alice");
308
const youngUsers = await ageIndex.getAll(IDBKeyRange.upperBound(25));
309
```
310
311
### Cursor Operations
312
313
Open cursors for efficient iteration over large datasets.
314
315
```typescript { .api }
316
/**
317
* Opens a cursor over the records matching the query
318
* Resolves with null if no matches are found
319
* @param query - Key or key range to match (optional)
320
* @param direction - Cursor direction (next, nextunique, prev, prevunique)
321
* @returns Promise resolving to cursor or null
322
*/
323
openCursor(
324
query?: StoreKey<DBTypes, StoreName> | IDBKeyRange | null,
325
direction?: IDBCursorDirection
326
): Promise<IDBPCursorWithValue<DBTypes, TxStores, StoreName, unknown, Mode> | null>;
327
328
/**
329
* Opens a cursor over the keys matching the query
330
* Resolves with null if no matches are found
331
* @param query - Key or key range to match (optional)
332
* @param direction - Cursor direction (next, nextunique, prev, prevunique)
333
* @returns Promise resolving to cursor or null
334
*/
335
openKeyCursor(
336
query?: StoreKey<DBTypes, StoreName> | IDBKeyRange | null,
337
direction?: IDBCursorDirection
338
): Promise<IDBPCursor<DBTypes, TxStores, StoreName, unknown, Mode> | null>;
339
```
340
341
**Cursor Usage Examples:**
342
343
```typescript
344
const tx = db.transaction("users", "readonly");
345
const userStore = tx.store;
346
347
// Iterate with cursor manually
348
let cursor = await userStore.openCursor();
349
while (cursor) {
350
console.log("User:", cursor.key, cursor.value);
351
cursor = await cursor.continue();
352
}
353
354
// Iterate over keys only
355
let keyCursor = await userStore.openKeyCursor();
356
while (keyCursor) {
357
console.log("User key:", keyCursor.key);
358
keyCursor = await keyCursor.continue();
359
}
360
361
// Cursor with query and direction
362
let filteredCursor = await userStore.openCursor(
363
IDBKeyRange.bound("user100", "user200"),
364
"prev" // Reverse order
365
);
366
while (filteredCursor) {
367
console.log("Filtered user:", filteredCursor.value);
368
filteredCursor = await filteredCursor.continue();
369
}
370
```
371
372
### Async Iteration
373
374
Use modern async iteration syntax for convenient data traversal.
375
376
```typescript { .api }
377
/**
378
* Iterate over the store using async iteration
379
* @returns Async iterable iterator over cursor values
380
*/
381
[Symbol.asyncIterator](): AsyncIterableIterator<
382
IDBPCursorWithValueIteratorValue<DBTypes, TxStores, StoreName, unknown, Mode>
383
>;
384
385
/**
386
* Iterate over the records matching the query
387
* @param query - Key or key range to match (optional)
388
* @param direction - Cursor direction (optional)
389
* @returns Async iterable iterator over cursor values
390
*/
391
iterate(
392
query?: StoreKey<DBTypes, StoreName> | IDBKeyRange | null,
393
direction?: IDBCursorDirection
394
): AsyncIterableIterator<
395
IDBPCursorWithValueIteratorValue<DBTypes, TxStores, StoreName, unknown, Mode>
396
>;
397
```
398
399
**Async Iteration Examples:**
400
401
```typescript
402
const tx = db.transaction("users", "readonly");
403
const userStore = tx.store;
404
405
// Iterate over all records
406
for await (const cursor of userStore) {
407
console.log("User:", cursor.key, cursor.value);
408
409
// Control iteration
410
if (cursor.value.age < 18) {
411
cursor.continue(); // Skip to next
412
}
413
}
414
415
// Iterate with query
416
for await (const cursor of userStore.iterate(IDBKeyRange.bound(100, 200))) {
417
console.log("User in range:", cursor.value);
418
419
// Early termination
420
if (cursor.value.name === "Target User") {
421
break;
422
}
423
}
424
425
// Iterate in reverse order
426
for await (const cursor of userStore.iterate(null, "prev")) {
427
console.log("User (reverse):", cursor.value);
428
}
429
430
// Collect results with async iteration
431
const activeUsers = [];
432
for await (const cursor of userStore.iterate()) {
433
if (cursor.value.status === "active") {
434
activeUsers.push(cursor.value);
435
}
436
}
437
438
await tx.done;
439
```
440
441
### Performance Optimization
442
443
Strategies for efficient object store operations.
444
445
**Batch Operations:**
446
447
```typescript
448
async function batchAddUsers(users: User[]) {
449
const tx = db.transaction("users", "readwrite");
450
const userStore = tx.store;
451
452
// Start all operations without awaiting individually
453
const promises = users.map(user => userStore.add(user));
454
455
// Wait for all operations and transaction completion
456
await Promise.all([...promises, tx.done]);
457
}
458
```
459
460
**Efficient Counting:**
461
462
```typescript
463
// Use count() instead of getAll().length for better performance
464
const userCount = await userStore.count();
465
466
// Count with filters using key ranges
467
const adultCount = await userStore.index("age").count(IDBKeyRange.lowerBound(18));
468
```
469
470
**Key-Only Queries:**
471
472
```typescript
473
// More efficient when you only need keys
474
const userKeys = await userStore.getAllKeys();
475
476
// Instead of
477
const users = await userStore.getAll();
478
const keys = users.map(user => user.id); // Less efficient
479
```