indexeddb 如何通过索引过滤条件,并进行排序,并限制 limit ?

我想通过 indexeddb 获取列表数据,类似实现以下 SQL 的结果:

select * from table where user_id = 101 and order_id < 1000 order by order order_id desc limit 20

简述下:
1.获取某个用户(101)的所有记录
2.要求 order_id < 1000
3.按照倒序返回 20 条数据。

最终的结果应该是:
user_id = 101的,order_id 为 979 - 999 区间的数据。

以上需求,实现起来感觉好难。

let value = [user_id];
let objectStore = this.db.transaction([storeName]).objectStore(storeName)
let indexCondition = objectStore.index(index)
indexCondition.getAll(value)

这样虽然可以获取到这个用户的所有数据,但是不能排序,也不能limit。

let value = [user_id];
let objectStore = this.db.transaction([storeName]).objectStore(storeName)
let indexCondition = objectStore.index(index)
indexCondition.openCursor(IDBKeyRange.only(value), 'prev');
var res = [];
request.onsuccess = function(event) {
    var cursor = event.target.result;
    if (cursor) {
        res.push(cursor.value);
        cursor.continue();
    } else {
        console.log('结束',res)
        resolve(res
    }
};

上面这个,虽然可以通过游标判断够条数,然后停止读取,实现 limit 。
但是不能满足 where order_id < 1000 的条件,这里返回的是整个用户所有的数据。

各位大佬,有没有好的解决方案呢?

阅读 6.9k
3 个回答

最终解决方案:
按照查询需求创建索引,这样缺点是不能动态调整,如果查询字段可变,就不能很好满足。

比如,上文需要按照 user_id = 101 过滤,并按照 order_id 过滤取 < 1000 的几条数据。
创建索引
[user_id, order_id]

查询按照以下方式就可以取到数据。

const request = indexCondition.openCursor(IDBKeyRange.bound([101, 0],[101, 1000]), 'prev')

  request.onsuccess = function(event) {
    var cursor = event.target.result;
    if (cursor) {
        res.push(cursor.value);
        if(limit && res.length >= limit){
            resolve(res);
        }else{
            cursor.continue();
        }
    } else {
        resolve(res);
    }
};

IndexedDB 跟后端那个关系型数据库(RDB)并不太一样,它并不遵守 ISO/IEC 9075 标准(即 SQL 标准),所以你要有过使用 SQL 的经验,再用起它来就会感觉别扭。这不是你一个人的感觉。

P.S. 说起来有一个被毙掉的 API —— WebSQL,才用的大家通常所熟悉的 SQL 语法,不过已经胎死腹中了。

题主可以尝试一下第三方的封装库,比如 db.js 之类的,写起来会“顺”一些。比如你要的过滤 + 分页,就是这个库里的 filter + limit.

这种需求建议你考虑jsstore ,它内部包装了indexeddb的API,上层封装了类似于SQL的查询接口,你这几个需求都可以实现。

它是自己维护了一套indexeddb的存储结构,在上层实现的类似于sql查询的效果

你不用关心底层indexeddb的维护了,比如dbversion之类的东西,几乎不会hang住,建议你考虑这个方案

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题