Iterate over collection
Hey, I have looked around but couldn't find a good way to do something like the following
const coll = myTable.where('key').equals('mykey')
coll.next().then((val) => console.log('got next value', val))
The idea is being able to pull values out of the collection one at a time, rather than getting all of them at once in memory like .each or .toArray would do.
As far as I understand using IndexedDB does support getting one value at a time when using cursor, so that shouldn't stop this from happening.
That could be done by using Collection.limit() or Collection.until().
const coll = myTable.where('key').equals('mykey')
coll.limit(1).each(val => console.log('got first value', val));
or
coll.until(val => {
console.log('got next value', val);
if (wanna stop here) return true; // Returning true will stop iteration
}).each(val => {}).then(...);
That said, if you really need a promise resolution for each found entry, being able to continue when you want to, it's not possible in current version. I've been thinking of introducting a Cursor class in Dexie that could could be used for next() or next(numberOfRecords). The main use case I've seen, is to accomplish paging better than just doing collection.offset(pageNo*pageSize).limit(pageSize). In that case, the native IDBCursor would be useless because it is tied to the transaction and the transaction would be gone when a user clicks next page link.
If we ever introduce a Cursor class in is introduced in Dexie, I believe it would be able to work either in-transaction or between transactions. When still in transaction, it could just use the IDBCursor. When original transaction is gone, this could be accomplished another way - by reording the last key and primary key used and reinvoking the query starting at that key.
Just an additional idea: if we implement a Cursor maybe we can use the es6 iterable protocol for it so that it works with for...of and the spread operator. (We will probably need async iteration which is not part of ES yet)
That's a good idea. If typeof Symbol !== 'undefined' && typeof Symbol.asyncIterator === 'symbol') we could defined method Symbol.asyncIterator on Collection.prototype. It could return the cursor that should implement the next() method returning a Promise. Could also have an explicit method openCursor(). That way, the following would be possible:
// ES2015
const cursor = db.friend.where('age').above(20).openCursor();
return (function next() {
return cursor.next().then(({value, done}) => {
if (!done) {
console.log(`next: ${value}`);
return next();
}
});
})();
// ES-next
for await (const friend of db.friend.where('age').above(20)) {
console.log(friend);
}
👍 came here looking for a asyncIterator. would love to have it.
What is the status here? Iterating in an async manner is paramount for using memory efficient queries. What is the current suggestion/solution for using a cursor based query in Dexie that would allow for await () constructs?