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