2011-06-19 17 views
24

Niedawno odkryłem (niestety), że WebSQL nie jest już obsługiwany dla HTML5 i że IndexedDB zastąpi go zamiast tego.Jak wykonać kwerendę przy użyciu wielu warunków w IndexedDB?

Zastanawiam się, czy istnieje sposób na zapytanie lub wyszukiwanie wpisów IndexedDB w podobny sposób, w jaki sposób mogę użyć SQL do wyszukania wpisu spełniającego wiele warunków.

Widziałem, że mogę przeszukiwać IndexedDB przy użyciu jednego warunku z KeyRange. Jednak nie mogę znaleźć sposobu na przeszukiwanie dwóch lub więcej kolumn danych bez przechwytywania wszystkich danych z bazy danych i wykonywania z pętlami.

Wiem, że to nowa funkcja, która jest ledwo zaimplementowana w przeglądarkach, ale mam projekt, który rozpoczynam i badam różne sposoby, w jakie mogłem to zrobić.

Dziękujemy!

+0

P.S. Próbowałem tego przy użyciu LocalStorage i przechowywania macierzy kodowanej JSON i używania pętli do sortowania moich warunków. Jednak mój stół ma 4000+ wpisów, a przejście przez wszystkie z nich zajmuje więcej niż (prawdopodobnie) 100 milisekund, co jest o wiele za długie. Jeśli użyłem IndexedDB, nie widzę, jak mogę to przyspieszyć, chyba że mogę wykonywać kwerendy z wieloma kolumnami. – jthereliable

+1

W skrócie: musisz [utworzyć indeks] (http://www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-createIndex) na właściwościach, które chcesz wyszukać, a następnie pobrać [indeks] (http : //www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-index) w transakcji, a następnie wywołaj [openCursor] (http://www.w3.org/TR/IndexedDB/#widl-IDBIndex- openCursor) w tym zakresie. Mogę wymyślić przykład, ale może mi to zająć dzień lub dwa ... – robertc

+0

Dzięki za odpowiedź. Próbowałem to zrobić, ale nie mogłem dowiedzieć się, jak wykonać zapytanie do indeksu multirow, aby zrobić coś takiego jak porównanie wielu kolumn w instrukcji WHERE SQL. Czy masz jakieś rady na ten temat? – jthereliable

Odpowiedz

25

Sprawdź to pytanie na this answer. Jest bardziej szczegółowy niż odpowiedź, którą tu podaję. Parametr keypath do metod store.createIndex i IDBKeyRange can be an array. Tak surowy przykład:

// In onupgradeneeded 
var store = db.createObjectStore('mystore'); 
store.createIndex('myindex', ['prop1','prop2'], {unique:false}); 

// In your query section 
var transaction = db.transaction('mystore','readonly'); 
var store = transaction.objectStore('mystore'); 
var index = store.index('myindex'); 
// Select only those records where prop1=value1 and prop2=value2 
var request = index.openCursor(IDBKeyRange.only([value1, value2])); 
// Select the first matching record 
var request = index.get(IDBKeyRange.only([value1, value2])); 
+1

jest drugi parametr opcji metody createIndex: multiEntry, który informuje indexedDB, czy indeks powinien zostać utworzony na każdym elemencie tablicy lub całej tablicy. Więcej informacji: http://www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-optionalParameters –

0

wspomnieć kilka propozycji dla kwerend relacje w mojej odpowiedzi na to pytanie, które mogą stanowić przedmiot zainteresowania:

Conceptual problems with IndexedDB (relationships etc.)

Co do zapytań wielu pól jednocześnie, że nie wygląda jak tam rodem sposób to zrobić w IndexedDB (mógłbym się mylić, wciąż jestem do niego nowy), ale możesz oczywiście stworzyć funkcję pomocniczą, która używa oddzielnego kursora dla każdego pola, i iterować nad nimi, aby zobaczyć, które rekordy spełniają wszystkie kryteria .

+0

Dzięki za odpowiedź. Tak, właśnie to, co doszedłem do wniosku, byłoby najlepszym/jedynym rozwiązaniem tego problemu. – jthereliable

1

Tak, otwieranie ciągłego zakresu klawiszy na indeksie jest prawie takie, jak w indeksowanym DB. Testowanie wielu warunków nie jest możliwe w IndexedDB. Musi to być zrobione w pętli kursora.

Jeśli znajdziesz rozwiązanie, proszę dać mi znać.

BTW, myślę, że kursor pętli może być bardzo szybki i wymagać mniej pamięci niż to możliwe z Sqlite.

+0

"Jeśli znajdziesz rozwiązanie, proszę dać mi znać." Wygląda na to, że odpowiedź Josha jest realnym rozwiązaniem. – user3334690

1

Jestem kilka lat późno, ale chcę tylko podkreślić, że odpowiedź Josha działa na założeniu, że wszystkie „kolumny” w kondycji są częścią indeks: keyPath.

Jeśli dowolne ze wspomnianych "kolumn" istnieje poza indeksem keyPath, należy przetestować warunki, w których są one uwzględnione w każdym wpisie utworzonym przez kursor utworzony w przykładzie. Więc jeśli masz do czynienia z takimi zapytaniami, lub Twój indeks nie jest unique, przygotuj się na napisanie kodu iteracyjnego!

W każdym przypadku sugeruję, abyś wypróbował BakedGoods, jeśli możesz reprezentować swoje zapytanie jako wyrażenie boolowskie.

W przypadku tego typu operacji zawsze będzie otwarty kursor w centralnym obiekcie objectStore, chyba że wykonujesz surowe zapytanie o równość (x ===? y, biorąc pod uwagę, że x jest obiektem objectStore lub kluczem indeksu), ale pozwoli to zaoszczędzić kłopot podczas pisania własny kod kursor iteracja:

bakedGoods.getAll({ 
    filter: "keyObj > 5 && valueObj.someProperty !== 'someValue'", 
    storageTypes: ["indexedDB"], 
    complete: function(byStorageTypeResultDataObj, byStorageTypeErrorObj){} 
}); 

Właśnie w trosce o pełną przejrzystość, BakedGoods jest utrzymywana przez moi.

1

Powiedzmy zapytanie SQL jest coś takiego:

SELECT * FROM TableName WHERE Column1 = 'value1' AND Column2 = 'value2' 

Equivalent Zapytanie w JsStore Biblioteka:

var Connection = new JsStore.Instance("YourDbName"); 
Connection.select({ 
    From: "YourTableName" 
    Where: { 
     Column1: 'value1', 
     Column2: 'value2' 
    }, 
    OnSuccess:function (results){ 
     console.log(results); 
    }, 
    OnError:function (error) { 
     console.log(error); 
    } 
}); 

Teraz, jeśli zastanawiasz się co JsStore jest, powiem ci, że to jest biblioteka do zapytania IndexedDB w uproszczony sposób. Click here, aby dowiedzieć się więcej o JsStore

Powiązane problemy