使用多个条件查询
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 维护。
【讨论】:
以上是关于使用多个条件查询的主要内容,如果未能解决你的问题,请参考以下文章
python使用pandas基于时间条件查询多个oracle数据表
条件检查之间的Mysql中有多个条件?有没有办法优化这个查询?