IndexedDBでは,インデックスを利用してデータベースから項目を検索することが出来ます。
完全一致で検索する処理は容易に実装が可能ですが,前方一致で検索したい場合にはひと工夫が必要です。
ひとことで言うと
インデックスに対するカーソルの範囲をこうすれば良い。
const str = 'hoge';
const nextStr = str.slice(0, -1) + String.fromCharCode(str.slice(-1).charCodeAt() + 1);
const range = IDBKeyRange.bound(str, nextStr, false, true);
//~~~~
index.openCursor(range);
//'hoge'から始まる項目にマッチ
下ごしらえ
こんな感じでデータベースdata
を初期化。
id
をキーパスとして使用し,name
で検索するためのインデックスを作成しています。
なお,例外処理や非同期処理の処理順などについては省略しています。
init
let DB;
const init= () =>{
const request = window.indexedDB.open('data', 1);
request.onupgradeneeded = e => {
const db = request.result;
const store = db.createObjectStore('data', {keyPath: 'id'});
//'name'で検索するためのインデックスを作成
store.createIndex('name', 'name');
}
request.onsuccess= e => {
DB = request.result;
}
}
init();
このデータベースに対し,次のデータを追加します。
add
const add= data => {
const db = DB;
const transaction = db.transaction('data', 'readwrite');
const store = transaction.objectStore('data');
store.put(data);
}
const data=[
{id: '0', name: 'hoge'},
{id: '1', name: 'fuga'},
{id: '2', name: 'hogehoge'}
];
add(data[0]);
add(data[1]);
add(data[2]);
範囲を指定してname
インデックスから項目を取得する関数を定義。
search
const search= range => {
const db = DB;
const transaction = db.transaction('data', 'readonly');
const store = transaction.objectStore('data');
const request = store.index('name').openCursor(range, 'next');
request.onsuccess= e => {
const cursor = request.result;
if (cursor){
console.log('検索結果:', cursor.value);
cursor.continue();
} else {
console.log('検索終了');
}
}
}
name
が"hoge"
に完全一致するデータを取得するにはこんな感じ。
完全一致
const range= IDBKeyRange.only("hoge");
search(range);
// 検索結果:{id: '0', name: 'hoge'}
// 検索終了
本題
name
が"hoge"
から始まるデータを取得するにはこうします。
前方一致
const str = 'hoge';
const nextStr = str.slice(0, -1) + String.fromCharCode(str.slice(-1).charCodeAt() + 1);
const range = IDBKeyRange.bound(str, nextStr, false, true);
search(range);
// 検索結果:{id: '0', name:'hoge'}
// 検索結果:{id: '2', name:'hogehoge'}
// 検索終了
nextStr
は,str
の最後の一文字を「文字コードにおける次の文字」に置き換えた文字列です。この場合は"hogf"
になります。
IDBKeyRange.bound(str, nextStr, false, true)
は,str
からnextStr
の範囲(ただしnextStr
を含まない)を指定しています。
すなわち,name
を辞書順に並べたときに"hoge"
と"hoge"
より後ろかつ"hogf"
より前にある文字列にマッチするので,"hoge"
から始まる項目を取得することができます。