【发布时间】:2014-03-15 04:52:35
【问题描述】:
有没有办法对 IndexedDB 中的同一属性执行 OR 或 IN 查询?
换句话说,我如何得到结果,
SELECT * FROM MyTable WHERE columnA IN ('ABC','DFT') AND columnB = '123thd'
谢谢!
【问题讨论】:
标签: indexeddb
有没有办法对 IndexedDB 中的同一属性执行 OR 或 IN 查询?
换句话说,我如何得到结果,
SELECT * FROM MyTable WHERE columnA IN ('ABC','DFT') AND columnB = '123thd'
谢谢!
【问题讨论】:
标签: indexeddb
如果没有多次请求,就无法进行开箱即用的OR 或IN 之类的查询。通常,此类问题的模式是“超出范围,提取比您需要的更多条目,并将其过滤为完全匹配”。
Chrome 团队 has proposed 一个 openKeyCursor() 方法作为此类查询的解决方案(感谢 Kyaw Tun 的建议,他是 SO 参与者和 ydn 的作者),但它不是标准也没有在其他浏览器中采用。
我能想到的最好的解决方案类似于w3线程的Comment #4:
columnB 上打开精确的键光标columnA 值 'ABC' 和 'DFT' 如果您通常期望columnB 为“123thd”的结果数量很大,并且大多数没有值“ABC”或“DFT”,那么您可能应该改为打开两个游标 -一个在columnA 上,带有值“ABC”,另一个在值“DFT”上。这是一种更复杂的方法,因为您必须手动合并两个结果集。
【讨论】:
使用复合索引的 2 个连续查询的解决方案:
使用派生属性进行 1 个查询的解决方案:
这种方法的缺点是您需要知道您计划执行的查询和 必须为每个查询调整此方法。这是你甚至应该做的事情 用 SQL。不幸的是,由于许多开发人员不关心正确的查询计划,这并不是那么明显,所以在使用 indexedDB 之前,它就像一个额外的要求学习和开始使用。但是,正确的查询计划确实会产生更好的性能。
// In onupgradeneeded
function myOnUpgradeNeeded(event) {
var db = event.target.result;
var store = db.createObjectStore('MyTable');
// Create a compound index on the derived property of columnA
// and the normal property of columnB
store.createIndex('A_ABC_OR_DFT_AND_B', ['ABC_OR_DFT_FLAG','columnB']);
}
function wrappedPut(db, obj, callback) {
// Set the flag property
// indexedDB cannot index booleans, so we use simple integer representation
// where 1 represents true, 0 represents false. But we can go further since
// we know that undefined properties dont appear in the index.
if(obj.columnA=='ABC'||obj.columnA=='DFT') {
obj.ABC_OR_DFT_FLAG = 1;
} else {
delete obj.ABC_OR_DFT_FLAG;
}
put(db, obj, callback);
}
// In your add/update function
function put(db, obj, callback) {
db.transaction('MyTable','readwrite').objectStore('myTable').put(obj).onsuccess = callback;
}
// Voila, a single efficient high speed query over all items
// in MyTable where columnA is ABC or DFT and where columnB
// is 123thd, using a single index, without using a 3rd party
// library, and without doing some horrible double cursor stuff
// in javascript, and just using the indexedDB API.
function runTheABCDFT123Query(db, onSuccess, onComplete) {
var tx = db.transaction('MyTable');
tx.onComplete = onComplete;
tx.objectStore('MyTable').index('A_ABC_OR_DFT_AND_B').openCursor(
IDBKeyRange.only([1,'123thd'])).onsuccess = function(event) {
if(event.target) {
onSuccess(event.target.value);
event.target.continue();
}
};
}
【讨论】:
indexedDB API 中不存在此功能。您只能过滤单个索引。您可以尝试围绕 indexedDB API 编写的库之一。其中一些提供额外的过滤器功能。
【讨论】:
这是一个简单的查询,等同于使用 JsStore Library 的 sql 查询
var Connection = new JsStore.Instance("MyDatabase");
Connection.select({
From: "MyTable",
Where:{
columnA : {In:['ABC','DFT')]},
columnB : '123thd'
},
OnSuccess:function (results){
console.log(results);
},
OnError:function (error) {
console.log(error);
}
});
希望这会节省您的时间和代码:)。
【讨论】: