Here's my test case on JS Bin.
想象一下,你有一个IndexedDB对象存储。您的对象非常简单,有两个属性“a”和“b”。两个属性都包含整数。并且因为您希望能够在对象存储中查询“a”和“b”的特定值,所以可以创建复合索引。以下是一些遵循此描述的代码:
var db;
request = indexedDB.open("test", 1);
request.onerror = function (event) { console.log(event); };
request.onupgradeneeded = function (event) {
var db = event.target.result;
db.onerror = function (event) { console.log(event); };
var store = db.createObjectStore("store", {keyPath: "id", autoIncrement: true});
store.createIndex("a, b", ["a", "b"], {unique: true});
store.add({a: 0, b: 0});
store.add({a: 1, b: 0});
store.add({a: 1, b: 1});
};
request.onsuccess = function (event) {
db = request.result;
db.onerror = function (event) { console.log(event); };
};
如果要从数据库中检索特定对象,则可以正常工作。所以如果你运行这个:
db.transaction("store").objectStore("store").index("a, b").get([1, 0]).onsuccess = function (event) { console.log(event.target.result); };
输出是:
Object {a: 1, b: 0, psid: 2}
奇妙。大。所以现在你要检索一系列值。说,你想把“b”固定为0,同时让“a”为0或1.现在奇怪的东西开始发生了。试试这段代码:
console.log("[a, b] bound from [0, 0] to [1, 0]");
db.transaction("store").objectStore("store").index("a, b").openCursor(IDBKeyRange.bound([0, 0], [1, 0])).onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
console.log(cursor.value);
cursor.continue();
} else {
console.log("[a, b] bound from [0, 0] to [2, 0]");
db.transaction("store").objectStore("store").index("a, b").openCursor(IDBKeyRange.bound([0, 0], [2, 0])).onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
console.log(cursor.value);
cursor.continue();
}
};
}
};
它产生这个输出:
[a, b] bound from [0, 0] to [1, 0]
Object {a: 0, b: 0, id: 1}
Object {a: 1, b: 0, id: 2}
[a, b] bound from [0, 0] to [2, 0]
Object {a: 0, b: 0, id: 1}
Object {a: 1, b: 0, id: 2}
Object {a: 1, b: 1, id: 3}
[0,0]和[1,0]之间的界限似乎工作正常。但是[0,0]和[2,0]之间的界限不是!结果它也返回[0,1]。为什么[1,0]作为上限但[2,0]不起作用?我觉得我必须犯下一个非常愚蠢的错误,或者从根本上误解某些事情。
万一你错过了,here is the link to this on JS Bin again。
Josh的编辑:我最初只用bound(x,y)
尝试了它,与bound(x,y,false,false)
相同。可以将其更改为bound(x,y,true,true)
here。输出
[a, b] bound from [0, 0] to [1, 0]
[a, b] bound from [0, 0] to [2, 0]
Object {a: 1, b: 0, id: 2}
Object {a: 1, b: 1, id: 3}
我对这些东西的理解仍然没有很好的直观理解。
答案 0 :(得分:1)
我试图在the other answer中解释这一点,但基本上是因为indexedDB规范中定义的短路数组排序。您正在使用范围查询,并且所有匹配都在第一个范围内。如果满足第一个范围标准,则其余范围正在做什么并不重要。
没有解决方案。您可以创建单独的索引(但遇到爆炸式索引问题)。您可以改为为每个对象创建预先计算的字段。换句话说,不要使用复合索引,在每次在indexedDB中添加/更新对象时更新对象的特殊派生隐藏字段时使用单个索引。
答案 1 :(得分:1)
您的索引不适用于查询b
的修正值。使用复合索引时,认为复合索引有两部分prefix and postfix。前缀密钥路径是您要过滤的路径。 postfix是您要订购的。
在您的情况下,您希望按b
进行过滤,然后按a
排序,因此索引应为['b', 'a']
。由于前缀和后缀keyPath可以有多个字段,因此可以使用IndexedDB进行非常复杂的查询。