如何创建一个IndexedDB复合键

27

我花了数小时的时间寻找这个问题的答案,只有通过试错才最终找到了解决方法。在Stack Overflow上记录下来以供日后搜索。

问题:

如何在indexeddb中创建复合键?

在对象存储中使用以下方式创建键:

var db;
var openRequest = indexedDB.open('myDB', 1);
openRequest.addEventListener('error', () => {
    console.error('Unable to open db');
});
openRequest.addEventListener('upgradeneeded', function(event){
    var store = db.createObjectStore('myStore', 
        {keyPath: /* composite key */ }
    );
});
openRequest.addEventListener('success', function(){
    db = openRequest.result;
});

我尝试过放置对象、多次定义,如何创建组合键?或者这是API的限制吗?
注意:如果您想查询使用范围的组合键,请查看this帖子。

@Josh 虽然所引用的帖子确实谈到了复合索引,但它主要关注的是使用IDBKeyRange来选择一系列元素。该帖子也没有解释如何为Indexeddb对象存储创建复合主键,因此我认为这篇帖子不是重复的。 - SnareChops
是的,绝对不是重复的。这是关于使用复合keyPath创建(和填充)对象存储的内容;所引用的主题是关于从这样一个存储中提取项目。两者彼此非常有效地补充。一起使用,它们非常有帮助;正如SnareChops所说,即使四年后,这仍没有得到很好的记录。 - Velojet
2个回答

48

A:

事实证明,答案非常简单,但在我查找的任何地方都没有得到很好的记录,一开始也不是很明显。使用一个字符串数组...

var store = db.createObjectStore('myStore', 
    {keyPath: ['id1', 'id2']}
);

同样的方式也可以创建复合索引。

如果需要处理复合键数据,请查看下面Malvineous的答案


数组元素不一定要是字符串;数字值同样适用。 - Velojet
@Velojet,这些字符串是属性名称,而不是键的值。但是,如果您将这样的数组传递给put,那么它就是键的值。 - rudolfbyker
1
感谢您的澄清,@rudolfbyker。我应该明确指出,我是在put操作的上下文中引用复合键数组:db.put(storename, item, [var1, var2]),其中var1var2是数字值。我的基本观点仍然成立,即虽然复合键本身可以是一个数组,但它不必是一个字符串数组。 - Velojet
@snareChops 感谢你的问答,我无法找到任何关于如何基于这个复合键检索数据的示例或文档。比如说,我想查找所有具有id1的记录,并从集合中提取最后一条记录。你能帮忙吗?我添加了像row1 => [id1 = abc & id2 = 1],row2 => [id1 = abc & id2 = 2]这样的行。 - Abdul Rehman
@Bsienn请看Malvineous刚刚发布的答案。 - SnareChops
@SnareChops 喜欢这个社区,感谢更新。虽然我已经弄明白了。干杯 - Abdul Rehman

6

补充一点,实际上使用复合键也不是那么清晰明了。

添加一个对象还不错:

myStore.add({
    id1: 'a',  // first part of key
    id2: 'b',  // second part of key
    etc: 'c',  // other data to store
});

然而,使用组合键再次获取对象并不那么明显。您需要将一个数组作为键传递,其中的值与最初传递给createObjectStore()keyPath数组中的顺序相同。

myStore.get(['a', 'b'])   // look for id1=a + id2=b

这里,数组中的第一个值(a)与上述答案中设置为id1keyPath[0]相匹配。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接