通过索引name and library_id
来获得文件对象存储,如下所示,
let objectStore = db.createObjectStore('file', { keyPath: 'id' });
tempStore.createIndex('nameLibId', ['attributes.name', 'attributes.library_id'], { unique: false });
对象库包含多个库ID的文件。我想将名称排序应用于特定库ID的文件。我尝试使用以下格式编制索引,但它返回的数据为空。
let self = this,
db = get(self, 'db'),
transaction = db.transaction(["file"], "readonly"),
objectStore = transaction.objectStore("file"),
index = objectStore.index('nameLibId'),
keyRange = IDBKeyRange.only('library_id')),
req = index.getAll(keyRange);
req.onsuccess = ((e)=>{
console.log(e.target.result); // returns empty array
});
随附了db模型的屏幕快照以供参考。
24536475
,abc
,created
,jhgf
和lastmodified
文件名属于名为123
的库ID。
Screen Shot..*
文件名属于另一个名为234
的库ID。
我只需要按给定库ID按名称排序的文件。任何帮助将不胜感激。
答案 0 :(得分:1)
如果索引基于属性数组,并且您想使用IDBKeyRange.only
进行匹配,则IDBKeyRange.only
的参数也应该是数组。现在,您正在将一个基本字符串值与一个属性数组值进行比较,其中当然没有任何匹配项。换句话说,您不能仅使用其中一部分来查询由两部分组成的数组。
此外,IDBKeyRange.only的参数不是属性名称,而是一个值。您想要指定一个与索引的键路径值集中匹配的值。例如,如果您的索引仅基于attributes.name,则您需要在该索引中指定一个特定的值,例如“ abc”。
因此,考虑到以上两点,并且考虑到您的索引不是单个值而是由两个属性组成的数组,因此您需要将参数修改为IDBKeyRange.only,以查找数组。像IDBKeyRange.only(['abc', 'yoktc....']);
之类的东西。
现在,由于您在代码中执行的操作实际上并未完成所需的操作,这使情况更加复杂。暂时忽略排序问题,在匹配此索引的行时,您只想使用id条件,而不是名称。因此,您可能很想尝试IDBKeyRange.only([undefined, 'asdf'])
。不幸的是,这根本不起作用,因为您无法指定undefined(您将收到javascript错误)。
因此,即使您只想将标准应用于其中一个值,也必须始终按两个值查询。这里的窍门是,您切换到使用不同于其他方法的方法。您使用IDBKeyRange.bound()
,并且还可以通过技巧来指定诸如“最小的可能的数字小于我的数字,而我的数字小于最大的数字”之类的条件。一个永远都是真的条件。您将“最小可能值”用作下边界,而将“最大可能值”用作上边界。
这里是您的例子。我认为name的最小可能值是空字符串。 name的最大可能值可能是任何非字母数字字符,因此让我们使用代字号“〜”。因此,现在我们将重写range参数。代替使用IDBKeyRange.only,我们使用IDBKeyRange.bound。看起来如下(大致):
var libId = ???;
var smallestNameValue = '';
var largestNameValue = '~';
var lowerBound = [smallestNameValue, libId];
var upperBOund = [largestNameValue, libId];
var range = IDBKeyRange.bound(lowerBound, upperBound);
现在,第二部分关于排序,以及使用具有多个部分的索引的主要警告(不要与multiPart索引属性ugh混淆)。而且我本人一直都在退缩,所以我什至在这里可能是错的,并且上面的方法行得通。上面的问题是,由于短路数组排序算法在indexedDB的比较函数中是如何工作的,因此第一个条件被满足,第二个条件被忽略了。您的查询将匹配所有内容,因为每个索引行均符合条件。因此,此方法的诀窍是始终首先查询重要条件,基本上要注意您指定条件的顺序。因此,这意味着您需要在创建索引时切换指定属性的顺序,以便可以先按libId然后按名称查询。
您想要执行createIndex('nameLibId',['attributes.name','attributes.library_id']);
而不是createIndex('nameLibId',['attributes.library_id', 'attributes.name']);
。这也意味着您需要交换下限和上限查询,例如var lowerBound = [libId, smallestNameValue];
(并且不要忘记切换鞋帮)。
正如我在回答中使用复合索引所提到的那样,您始终可以使用indexedDB.cmp
进行实验。现在,在此网页上打开控制台。在控制台中,输入以下内容:
indexedDB.cmp(['', '5'], ['~', '5']);
看看结果。
一些最后的笔记: