Can somebody suggest how to get multiple key value from IndexedDB objectstore ? I have done multiple options, but didn't work none. Created indexedDb here
$provide.value('dbModel', {
name: 'TestDB',
version: '1',
instance: {},
objectStoreName: {
dashboards: 'Appointment'
},
upgrade: function (e) {
var db = e.target.result;
if (!db.objectStoreNames.contains('Appointment')) {
var calendarobj = db.createObjectStore('Appointment', {
keyPath: 'AppointmentId'
});
calendarobj.createIndex("AppointmentId", "AppointmentId", { multiEntry: true });
}
}
});
And the Data looks like
KeyPath-AppointmentId Value
===================== =====
1 Test 1
2 Test 2
3 Test 3
I have getObjectStore method to get the objectstorename instance.
getObjectStore: function (objectStoreName, mode) {
var modeact = mode || _db.transactionTypes.readonly;
var txn = _db.instance.transaction(objectStoreName, modeact);
var store = txn.objectStore(objectStoreName);
return store;
}
var keys = [1,2]; // Want to get the First two record which has value 'Test 1' and 'Test 2'
var store = _db.getObjectStore(objectStoreName);
var tagIndex = store.index(store.keyPath); //AppointmentId
var request = tagIndex.openCursor(IDBKeyRange.only(keys));
//var request = tagIndex.get(keys);
request.onsuccess = function (event) {
console.log(event.result);
}
Using [1, 2]
as you do won't work - that's a key which happens to be an array with two members. Indexed DB currently doesn't understand using lists or sets of keys for querying.
You have a handful of options:
1 - Issue two get requests in parallel. (Since the order is guaranteed, the second request will finish after the first and you know both results will have been returned.)
var results = [];
store.get(1).onsuccess = function(e) {
results.push(e.target.result);
};
store.get(2).onsuccess = function(e) {
results.push(e.target.result);
// results will have the values
};
2 - Use a cursor and a range:
var results = [];
store.openCursor(IDBKeyRange.bound(1, 2)).onsuccess = function(e) {
var cursor = e.target.result;
if (cursor) {
results.push(cursor.value);
cursor.continue();
} else {
// results will have the values
}
};
3 - Use getAll with a range (newer browsers only - fall back to a cursor if not available)
store.getAll(IDBKeyRange.bound(1, 2)).onsuccess = function(e) {
// e.target.result will have the entries
};
Note that in options 2 and 3 which use a range you would also get a records with a key of 1.5
if one existed.
This could be duplicated with Multiple keys query in IndexedDB (Similar to OR in sql), but I have no permission to report duplication, so I would post the answer again. Hope it helps.
// [store]: object store
// [keys]: array of keys
// return: An object of key-value pairs
const get = (store, keys) =>
Promise.all(
keys.map(
(key) =>
new Promise((resolve, reject) => {
const request = store.get(key);
request.onsuccess = ({ target: { result } }) => resolve(result);
request.onerror = ({ target: { error } }) => reject(error);
})
)
).then((values) =>
keys.reduce(
(result, key, index) => ((result[key] = values[index]), result),
{}
)
);
const request = indexedDB.open("test");
request.onupgradeneeded = ({ target: { result: db } }) => {
db.createObjectStore("settings").transaction.oncomplete = ({
target: { db },
}) => {
const store = db
.transaction("settings", "readwrite")
.objectStore("settings");
store.add(123, "foo");
store.add(456, "bar");
};
};
request.onsuccess = ({ target: { result: db } }) => {
get(db.transaction("settings").objectStore("settings"), [
"foo",
"bar",
"buz",
]).then(console.log); // {foo: 123, bar: 456, buz: undefined}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With