2011-06-19 1 views
24

私は最近、WebSQLがHTML5でサポートされなくなり、IndexedDBが代わりに代わりになることを発見しました(悲しいことに)。IndexedDBで複数の条件を使用してクエリを実行するにはどうすればよいですか?

SQLを使用して複数の条件を満たすエントリを検索する方法と同様に、IndexedDBのエントリをクエリまたは検索する方法があるかどうかは疑問です。

KeyRangeを使用して1つの条件を使用してIndexedDBを検索することができます。しかし、私は、データベースからすべてのデータを取得してforループで処理することなく、2つ以上のデータ列を検索する方法を見つけることはできません。

これはブラウザでほとんど実装されていない新しい機能だと知っていますが、私が始めているプロジェクトがあり、私はそれをやり遂げる方法を研究しています。

ありがとうございました!

+0

P.S.私はこれをLocalStorageを使って試して、JSONエンコードされた配列を格納し、forループを使って条件をソートしました。しかし、私のテーブルは4000以上のエントリであり、それらのすべてをループするには長すぎる(おそらく)100ミリ秒以上かかる。 IndexedDBを使用した場合、複数列のクエリを実行できない限り、どのように高速化できるのか分かりません。 – jthereliable

+1

要約:クエリを実行するプロパティで[インデックスを作成する](http://www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-createIndex)する必要があります。次に、[index](http ://www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-index)を呼び出してから、[openCursor](http://www.w3.org/TR/IndexedDB/#widl-IDBIndex- openCursor)メソッドを使用します。私は例を考え出すことができますが、それは私に1日かそれ以上かかるかもしれません... – robertc

+0

応答に感謝します。私はそれをしようとしましたが、SQLのWHERE文で複数列の比較のような処理を行うために複数行インデックスをクエリする方法を見つけることができませんでした。あなたはこれについてアドバイスをしていますか? – jthereliable

答えて

25

同じ質問に対してthis answerを確認してください。それは私がここで答えるよりも詳細です。 store.createIndexおよびIDBKeyRangeメソッドのkeypathパラメーターcan be an array。だから、粗製の例:

// 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

createIndexメソッドのオプションの2番目のパラメータがあります。multiEntryは、配列内の各要素または配列全体でインデックスを作成する必要があるかどうかをindexedDBに通知します。詳細はこちら:http://www.w3.org/TR/IndexedDB/#widl-IDBObjectStore-createIndex-IDBIndex-DOMString-name-DOMString-sequence-DOMString--keyPath-IDBIndexParameters-オプションパラメータ –

0

は、私が興味のあるこの質問に私の答えに関係を照会するためのいくつかの提案を言及:ネイティブがありますように

Conceptual problems with IndexedDB (relationships etc.)

一度に複数のフィールドを照会するよう、それは見ていません私は間違っている可能性があります(私はまだそれが新しいです)しかし、あなたは確かに各フィールドのために別のカーソルを使用し、それらの上にすべての条件を満たすレコードを見るために繰り返しヘルパー関数を作成することができます。

+0

答えをありがとう。はい、それは私が結論したことは、このために最高の/唯一の解決策になるでしょう。 – jthereliable

1

はい、インデックスの連続キー範囲を開くのは、indexedDBの場合とほとんど同じです。複数の条件のテストはIndexedDBでは不可能です。これはカーソルループで行わなければなりません。

解決策が見つかったら、教えてください。

私はカーソルが非常に高速になり、Sqliteで可能なメモリよりも少ないメモリを必要とすると思います。

+0

"解決策を見つけたらお知らせください。"ジョシュの答えは実行可能な解決策だと思われます。 – user3334690

1

私は近年のカップルだけど、私はただジョシュの答えが条件の「列」の全てがその一部であることを前提に動作することを指摘したいと思いますインデックスのkeyPath

インデックスのkeyPathの外に上記の「列」が存在する場合は、この例で作成したカーソルが反復処理する各エントリで、それらの条件をテストする必要があります。そのようなクエリを扱っている場合や、インデックスがuniqueでない場合は、繰り返しコードを書く準備をしてください!

いずれにしても、クエリをブール式として表すことができる場合は、BakedGoodsをチェックアウトすることをおすすめします。

厳密な等価クエリ(x ===? y、与えられたxはobjectStoreまたはインデックスキーです)を実行しない限り、これらのタイプの操作では常にfocal ObjectStoreにカーソルが表示されますが、独自のカーソルの反復コード:

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

ただ、完全な透明性のために、BakedGoodsはMOIによって維持されています。

1

のは、あなたのSQLクエリのようなものであるとしましょう:

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

JsStore、ライブラリ内の等価問合せ:あなたはJsStoreが何であるかを不思議に思っている場合

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); 
    } 
}); 

さて、私はそれはあなたを教えてみましょうライブラリを使用してIndexedDBを簡単にクエリできます。 Click here詳細については、JsStore

関連する問題