html5 indexeddb 排序,html5 – 在IndexedDB中,有没有办法进行排序复合查询?
本回答中使用的術(shù)語“復(fù)合查詢”是指在其WHERE子句中涉及多個(gè)條件的SQL SELECT語句。雖然indexedDB規(guī)范中沒有提到這樣的查詢,但您可以通過創(chuàng)建一個(gè)包含一組屬性名稱的keypath的索引來近似復(fù)合查詢的行為。
這與創(chuàng)建索引時(shí)使用多條目標(biāo)志完全無關(guān)。多條目標(biāo)志調(diào)整indexedDB如何在單個(gè)數(shù)組屬性上創(chuàng)建索引。我們正在索引對象屬性數(shù)組,而不是對象的單個(gè)數(shù)組屬性的值。
創(chuàng)建索引
在此示例中,’name’,’gender’和’age’對應(yīng)于存儲(chǔ)在學(xué)生對象存儲(chǔ)中的學(xué)生對象的屬性名稱。
// An example student object in the students store
var foo = {
'name': 'bar',
'age': 15,
'gender': 'M'
};
function myOnUpgradeNeeded(event) {
var db = event.target.result;
var students = db.createObjectStore('students');
var name = 'males25';
var keyPath = ['name', 'gender', 'age'];
students.createIndex(name, keyPath);
}
在索引上打開一個(gè)光標(biāo)
然后可以在索引上打開一個(gè)光標(biāo):
var students = transaction.objectStore('students');
var index = students.index('males25');
var lowerBound = ['AAAAA','male',26];
var upperBound = ['ZZZZZ','male',200];
var range = IDBKeyRange.bound(lowerBound, upperBound);
var request = index.openCursor(range);
然而,由于我要解釋的原因,這并不總是奏效。
另外:使用rangeCursor或get的range參數(shù)是可選的。如果不指定范圍,則IDBKeyRange.only將被隱式使用。換句話說,您只需要為有界游標(biāo)使用IDBKeyRange。
基本指標(biāo)概念
指數(shù)就像對象商店,但不是直接可變的。而是在引用的對象存儲(chǔ)上使用CRUD(創(chuàng)建讀取更新刪除)操作,然后,indexedDB會(huì)自動(dòng)將更新級(jí)聯(lián)到索引。
了解排序是理解指標(biāo)的基礎(chǔ)。索引基本上只是一個(gè)特別排序的對象集合。在技??術(shù)上,它也被過濾,但我會(huì)在一會(huì)兒觸及。通常,當(dāng)您在索引上打開游標(biāo)時(shí),您將根據(jù)索引的順序進(jìn)行迭代。此順序可能并且可能與引用對象存儲(chǔ)中的對象的順序不同。該順序很重要,因?yàn)檫@樣可以使迭代更有效率,并允許自定義的下限和上限在索引特定順序的上下文中是有意義的。
索引中的對象在商店發(fā)生更改時(shí)排序。將對象添加到商店時(shí),將其添加到索引中的正確位置。排序歸結(jié)為一個(gè)比較函數(shù),類似于Array.prototype.sort,它比較兩個(gè)項(xiàng)目,并返回一個(gè)對象是否小于另一個(gè),大于另一個(gè)對象或相等。因此,我們可以通過深入了解比較功能的更多細(xì)節(jié)來更好地理解排序行為。
字符串按字典順序比較
這意味著,例如,’Z’小于’a’,字符串’10’大于字符串’020’。
使用規(guī)范定義的順序比較不同類型的值
例如,該規(guī)范指定字符串類型值在日期類型值之前或之后。值不包含什么,只是類型。
IndexedDB不會(huì)為您強(qiáng)制類型。你可以在腳下射擊自己。你通常不想比較不同的類型。
具有未定義屬性的對象不會(huì)出現(xiàn)在其關(guān)鍵字由一個(gè)或多個(gè)這些屬性組成的索引中
正如我所提到的,索引可能并不總是包括引用對象存儲(chǔ)中的所有對象。將對象放入對象存儲(chǔ)中時(shí),如果索引所基于的屬性缺少值,則對象將不會(huì)出現(xiàn)在索引中。例如,如果我們有一個(gè)我們不知道年齡的學(xué)生,并且我們將它插入學(xué)生商店,那么特定的學(xué)生不會(huì)出現(xiàn)在男性25的索引中。
記住這一點(diǎn),當(dāng)你想知道為什么在索引上迭代游標(biāo)時(shí)不會(huì)出現(xiàn)一個(gè)對象。
還要注意null和空字符串之間的細(xì)微差別。空字符串不是缺少的值。具有空字符串的屬性的對象仍然可以基于該屬性出現(xiàn)在索引中,但如果屬性存在但未定義或不存在,則該索引中不會(huì)出現(xiàn)該索引。如果它不在索引中,則在索引上迭代游標(biāo)時(shí),不會(huì)看到它。
創(chuàng)建IDBKeyRange時(shí),必須指定數(shù)組keypath的每個(gè)屬性
創(chuàng)建一個(gè)下限或上限時(shí),必須為數(shù)組關(guān)鍵字中的每個(gè)屬性指定一個(gè)有效值,以便在該范圍上打開光標(biāo)時(shí)在范圍內(nèi)使用。否則,您會(huì)收到一些類型的Javascript錯(cuò)誤(因?yàn)g覽器而異)。例如,您不能創(chuàng)建一個(gè)范圍,例如IDBKeyRange.only([undefined,’male’,25]),因?yàn)閚ame屬性未定義。
令人困惑的是,如果你指定錯(cuò)誤類型的值,例如IDBKeyRange.only([‘male’,25]),其中name是未定義的,你不會(huì)在上面的意義上得到錯(cuò)誤,但是你會(huì)得到無意義的結(jié)果。
這個(gè)一般規(guī)則有一個(gè)例外:您可以比較不同長度的數(shù)組。因此,從技術(shù)上講,您可以從范圍中省略屬性,前提是您從數(shù)組的末尾執(zhí)行此操作,并適當(dāng)?shù)亟財(cái)鄶?shù)組。例如,您可以使用IDBKeyRange.only([‘josh’,’male’])。
短路數(shù)組排序
將Array類型的值與Array的其他值進(jìn)行比較,如下所示:
>令A(yù)為第一個(gè)數(shù)組值,B為第二個(gè)數(shù)組值。
>把長度作為A長度和B長度的較小者。
讓我成為0。
>如果A的第i個(gè)值小于B的第i個(gè)值,則A較少
比B.跳過剩下的步驟。
>如果A的第i個(gè)值大于B的第i個(gè)值,則A大于B.跳過其余步驟。
>增加我1。
>如果我不等于長度,請返回到步驟4.否則繼續(xù)下一步。
>如果A的長度小于B的長度,則A小于B.如果A的長度大于B的長度,則A大于B.否則A和B相等。
捕獲在步驟4和5:跳過剩余的步驟。這基本上意味著如果我們比較兩個(gè)數(shù)組用于順序,例如[1,’Z’]和[0,’A’],則該方法僅考慮第一個(gè)元素,因?yàn)樵谠擖c(diǎn)1是>由于短路評(píng)估(規(guī)格中的步驟4和5),它永遠(yuǎn)不會(huì)檢查Z對A。
所以,早期的例子是不會(huì)奏效的。它實(shí)際上更像如下:
WHERE (students.name >= 'AAAAA' && students.name <= 'ZZZZZ') ||
(students.name >= 'AAAAA' && students.name <= 'ZZZZZ' &&
students.gender >= 'male' && students.gender <= 'male') ||
(students.name >= 'AAAAA' && students.name <= 'ZZZZZ' &&
students.gender >= 'male' && students.gender <= 'male' &&
students.age >= 26 && students.age <= 200)
如果您在SQL或通用編程中有這樣的布爾子句的任何經(jīng)驗(yàn),那么您已經(jīng)應(yīng)該認(rèn)識(shí)到整套條件不一定涉及。這意味著您將無法獲取所需的對象列表,這就是為什么您無法真正獲得與SQL復(fù)合查詢相同的行為。
處理短路
在當(dāng)前的實(shí)現(xiàn)中,您不能輕易避免這種短路行為。在最壞的情況下,您必須將存儲(chǔ)/索引中的所有對象加載到內(nèi)存中,然后使用自己的自定義排序功能對集合進(jìn)行排序。
有辦法盡量減少或避免一些短路問題:
例如,如果您使用的是index.get(array)或index.openCursor(array),那么就沒有任何短路問題。整場比賽還是整場比賽。在這種情況下,比較功能只是評(píng)估兩個(gè)值是否相同,而不是一個(gè)是大于還是小于另一個(gè)。
其他技術(shù)要考慮:
>將關(guān)鍵字的元素從最窄到最大重新排列。基本上提供早期的夾具,可以切斷一些不需要的短路結(jié)果。
>將包裝的對象存儲(chǔ)在使用特殊定制屬性的商店中,以便可以使用非數(shù)組關(guān)鍵字(非復(fù)合索引)對其進(jìn)行排序,或者可以使用不受短組合索引影響的復(fù)合索引,電路行為。
>使用多個(gè)索引。這導(dǎo)致了exploding index problem.注意這個(gè)鏈接是關(guān)于另一個(gè)no-sql數(shù)據(jù)庫,但是相同的概念和解釋適用于indexedDB,并且鏈接是一個(gè)合理(冗長和復(fù)雜的)解釋,所以我不在這里重復(fù)。
> indexedDB(規(guī)范和Chrome實(shí)現(xiàn))的創(chuàng)建者之一最近建議使用cursor.continue:https://gist.github.com/inexorabletash/704e9688f99ac12dd336
使用indexedDB.cmp進(jìn)行測試
cmp function提供了一種快速簡單的方法來檢查排序是如何工作的。例如:
var a = ['Hello',1];
var b = ['World',2];
alert(indexedDB.cmp(a,b));
indexedDB.cmp函數(shù)的一個(gè)不錯(cuò)的屬性是它的簽名與Array.prototype.filter和Array.prototype.sort的函數(shù)參數(shù)相同。您可以輕松地從控制臺(tái)測試值,而無需處理連接/ schemas /索引和所有這些。此外,indexedDB.cmp是同步的,所以您的測試代碼不需要涉及async回調(diào)/承諾。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的html5 indexeddb 排序,html5 – 在IndexedDB中,有没有办法进行排序复合查询?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android上垂直跑马灯,androi
- 下一篇: 视频容器与编解码器的区别