使用多个条件查询

Posted

技术标签:

【中文标题】使用多个条件查询【英文标题】:Query using multiple conditions 【发布时间】:2011-09-18 08:07:03 【问题描述】:

我最近(遗憾地)发现 html5 不再支持 WebSQL,IndexedDB 将取而代之。

我想知道是否有任何方法可以像使用 SQL 搜索满足多个条件的条目一样查询或搜索 IndexedDB 的条目。

我发现我可以使用 KeyRange 的一个条件来搜索 IndexedDB。但是,如果不从数据库中获取所有数据并使用 for 循环进行操作,我似乎找不到任何方法来搜索两列或多列数据。

我知道这是一个几乎没有在浏览器中实现的新功能,但我有一个正在启动的项目,我正在研究我可以做到的不同方法。

谢谢!

【问题讨论】:

P.S.我尝试使用 LocalStorage 并存储 JSON 编码数组并使用 for 循环对我的条件进行排序。但是,我的表有 4000 多个条目,遍历所有条目需要超过(可能)100 毫秒,这太长了。如果我使用 IndexedDB,除非我可以进行多列查询,否则我看不出如何加快速度。 简而言之:您需要在要查询的属性上create an index,然后在事务中获取index,然后在其上调用openCursor 方法。我可以举个例子,但可能需要一天左右的时间...... 感谢您的回复。我试过这样做,但我不知道如何查询多行索引以在 SQL 的 WHERE 语句中执行多列比较之类的操作。您对此有什么建议吗? 我将在接下来的几天内尝试制定一个示例并发布正确的答案。 In IndexedDB, is there a way to make a sorted compound query? 的可能副本 【参考方案1】:

查看this answer 来解决同样的问题。它比我在这里给出的答案更详细。 store.createIndex 和 IDBKeyRange 方法 can be an array 的 keypath 参数。所以,粗略的例子:

// In onupgradeneeded
var store = db.createObjectStore('mystore');
store.createIndex('myindex', ['prop1','prop2'], unique:false);

// In your query section
var transaction = db.transaction('mystore','readonly');
var store = transaction.objectStore('mystore');
var index = store.index('myindex');
// Select only those records where prop1=value1 and prop2=value2
var request = index.openCursor(IDBKeyRange.only([value1, value2]));
// Select the first matching record
var request = index.get(IDBKeyRange.only([value1, value2]));

【讨论】:

createIndex 方法的选项有第二个参数:multiEntry,它告诉 indexedDB 是应该在数组中的每个元素上还是在整个数组上创建索引。更多信息在这里:w3.org/TR/IndexedDB/… 使用 "index.getAll( [value1, value2] ) " 注意:value1 和 2 不能未定义,否则会报错 - The parameter is not a valid key。 如果有人在查看@MichaRoon 的链接,你必须用这个锚点少滚动:w3.org/TR/IndexedDB/#index-construct【参考方案2】:

假设您的 SQL 查询类似于:

SELECT * FROM TableName WHERE Column1 = 'value1' AND Column2 = 'value2'

JsStore 库中的等效查询:

var Connection = new JsStore.Instance("YourDbName");
Connection.select(
    From: "YourTableName"
    Where: 
        Column1: 'value1',
        Column2: 'value2'
    ,
    OnSuccess:function (results)
        console.log(results);
    ,
    OnError:function (error) 
        console.log(error);
    
);

现在,如果您想知道 JsStore 是什么,让我告诉您它是一个以简化方式查询 IndexedDB 的库。 Click here 了解更多关于 JsStore

【讨论】:

【参考方案3】:

我在回答这个问题时提到了一些关于查询关系的建议,这可能会引起人们的兴趣:

Conceptual problems with IndexedDB (relationships etc.)

关于一次查询多个字段,在 IndexedDB 中似乎没有本地方法可以做到这一点(我可能是错的;我还是新手),但您当然可以创建一个辅助函数为每个字段使用一个单独的光标,并遍历它们以查看哪些记录符合所有条件。

【讨论】:

【参考方案4】:

是的,在索引上打开连续键范围几乎就是 indexedDB 中的内容。在 IndexedDB 中无法测试多个条件。必须在游标循环上完成。

如果您找到解决方案,请告诉我。

顺便说一句,我认为循环游标可能非常快,并且比使用 Sqlite 需要的内存更少。

【讨论】:

【参考方案5】:

我晚了几年,但我只想指出,乔希的回答是基于条件中的所有“列”都是索引keyPath 的一部分的假设。

如果任何上述“列”存在于索引的keyPath 之外,则必须在示例中创建的游标迭代的每个条目上测试涉及它们的条件。因此,如果您正在处理此类查询,或者您的索引不是unique,请准备好编写一些迭代代码!

无论如何,如果您可以将查询表示为布尔表达式,我建议您查看BakedGoods。

对于这些类型的操作,除非您执行严格的相等查询(x ===? y,假设 x 是 objectStore 或索引键),否则它将始终在焦点 objectStore 上打开一个游标,但它会为您省去麻烦编写自己的光标迭代代码:

bakedGoods.getAll(
    filter: "keyObj > 5 && valueObj.someProperty !== 'someValue'",
    storageTypes: ["indexedDB"],
    complete: function(byStorageTypeResultDataObj, byStorageTypeErrorObj)
);

为了完全透明,BakedGoods 由 moi 维护。

【讨论】:

以上是关于使用多个条件查询的主要内容,如果未能解决你的问题,请参考以下文章

在使用计划查询运行 BigQuery 作业之前处理多个条件

python使用pandas基于时间条件查询多个oracle数据表

条件检查之间的Mysql中有多个条件?有没有办法优化这个查询?

Mysql查询详解(条件查询、子查询、模糊查询、连接查询。。。)

使用多个连接和条件优化 SQL 查询

使用mybatis框架实现带条件查询-多条件