IndexedDBにはまってます。(その22)で予告の通り、カーソルの移動で、インデックスキー(補キー)による操作を紹介します。
今回もコピペコード全てをテキストファイル「code_IndexedDB_23.txt.zip」にまとめてアップロードしました。ご利用ください。
最初に閑話です。
IndexedDBにはまってます。(その15)と(その17)、(その18)のコードを見返してたら「(event)」と「(exception)」の両方が「(e)」と表記されていて、分かち書きされていないところが散見されました。ご注意ください。(開発しているソースコードでは分かちていないので、そのまま持ってきちゃったみたいです。すみません。)
閑話休題。
今回は(その15)のインデックスキー(補キー)版になります。
ちゃっちゃとWebブラウザ(Google Chromeを利用)のコンソールを利用して、つぎのインデックスキー(補キー)登録用とレコード格納用配列を登録して、レコードの格納までを済ませます。
コピペコードファイルの「登録用インデックスキー(補キー)の配列」「レコードの配列」を登録して、つづけて「オブジェクトストア生成と共にインデックスキー(補キー)登録」と「レコードの格納」を実行します。
const storeIndex = [
{name:'indexEn', path:'index.en', unique:false, multi:false},
{name:'indexSn', path:'index.sn', unique:false, multi:false},
{name:'id', path:'id', unique:true, multi:false},
{name:'attributeArray', path:['attribute','note'], unique:true, multi:false},
{name:'indexArray', path:['index.en','id'], unique:false, multi:false},
{name:'tagMulti', path:'tag', unique:false, multi:true}
];
const records = [
{key:2, data:{index:{en:1, sn:'SN0003'}, date:0, title:'ZINC', attribute:'transition', tag:['plate','Zn','shingle','brass'], note:'Zn', id:2}},
{key:6, data:{index:{en:2, sn:'SN0001'}, date:0, title:'GOLD', attribute:'transition', tag:['coin','jewelry','plate','Au','finger'], note:'Au', id:6}},
{key:5, data:{index:{en:3, sn:'SN0002'}, date:0, title:'SILVER', attribute:'transition', tag:['coin','jewelry','plate','tableware'], note:'Ag', id:5}},
{key:7, data:{index:{en:4, sn:'SN0004'}, date:0, title:'PLATIUM', attribute:'transition', tag:['css','jewelry','plate','catalyst'], note:'Pt', id:7}},
{key:1, data:{index:{en:5, sn:'SN0005'}, date:0, title:'COPPER', attribute:'transition', tag:['coin','pans','plate','shingle','brass'], note:'Cu', id:1}},
{key:3, data:{index:{en:6, sn:'SN0006'}, date:0, title:'ALUMINUM', attribute:'post-transition', tag:['coin','sash','pans','Macbook'], note:'Al', id:3}},
{key:9, data:{index:{en:7, sn:'SN0009'}, date:0, title:'TIN', attribute:'post-transition', tag:['pewter','cup','plate','suzunari'], note:'Sn', id:8}},
{key:4, data:{index:{en:9, sn:'SN0011'}, date:0, title:'LEAD', attribute:'post-transition', tag:['solder','bullet','glass','battery'], note:'Pb', id:9}}
];
早々にラングオブジェクトを生成できる様にしておきます。
コピペコードファイルの「ラングオブジェクトを生成するメソッド」を登録します。
(その15)同様にレコードの取得から紹介します。
IndexedDBにはまってます。(その21)と(その22)で紹介したところの、インデックオブジェクトの取得操作が挿入される以外は、ほぼ同じです。まずはコンソールで実行を確認してから説明します。
コピペコードファイルの「カーソル移動:インデックスキー(補キー)’attributeArray’によるレコード取得」を実行します。
レコードが取得できました。(よね?)
(コピペコードファイルの実行コードを見て比較しながらでお願いします。)
コード内の「//任意のインデックスキー(補キー)をパラメータにインデックスオブジェクトを取得する。」の前まではプライマリキー(主キー)の場合と同じです。
そして、その下は(その21)と(その22)のコードの「//ラングオブジェクト生成」の前までと、つぎの枠組みは同じです。インデックスオブジェクトの取得試行が成されてます。
//任意のインデックスキー(補キー)をパラメータにインデックスオブジェクトを取得する。
let indexObject = null;
try {
indexObject = objectStore.index('attributeArray');
} catch(exception) {
console.error(`例外が発生しました。_>${exception.message}`);
}
let indexObject = null;
try {
indexObject = objectStore.index('attributeArray');
} catch(exception) {
console.error(`例外が発生しました。_>${exception.message}`);
}
if(indexObject !== null) {
//ラングオブジェクト生成
const range = newRange({start:{v:['post-transition','Sn'], b:false}, end:{v:['transition','Cu'], b:false}});
//ここにカーソルの移動処理が入る。
}
例外が発生せずに、インデックスオブジェクトが取得できれば「//ラングオブジェクト生成」の実行に到達します。
ちなみに、ラングオブジェクトはつぎのように指定してます。アプリケーション画面でインデックスキー(補キー)「attributeArray」項目をアクティブにすると値の並びが確認できます。
const range = newRange({start:{v:['post-transition','Sn'], b:false}, end:{v:['transition','Cu'], b:false}});
(注意)順番が変更になってます。ごめんなさい。
(その15)では、「ラングオブジェクト生成」の前の「インデックスオブジェクト取得」コードより先に「//ラングオブジェクト生成」とカーソル移動パラメータのために定数宣言をしてました。
しかし、ここでは「//ここにカーソルの移動処理が入る。」の前の位置に、つぎのように入れます。
インデックスオブジェクトが取得できるとも限らないのに、生成や宣言をするのは尚早と判断して変更しました。(悪しからず。)
//ラングオブジェクト生成
const range = newRange({start:{v:['post-transition','Sn'], b:false}, end:{v:['transition','Cu'], b:false}});
//カーソル移動方向キーワード
const direction = 'next';
//カーソル移動ステップ(整数)
const cursorStep = 1;
カーソル移動パラメータの値については、(その15)と同じです。
そして、(その21)でcountメソッドの処理を記述した部分にあたります。「//ここにカーソルの移動処理が入る。」に、つぎのコードが入ります。(確認まで前述の定数宣言も入れてます。)
//カーソル移動方向キーワード
const direction = 'next';
//カーソル移動ステップ(整数)
const cursorStep = 1;
let cursorRequest = null;
try {
//インデックスキー(補キー)のカーソルを生成する。
cursorRequest = indexObject.openCursor(range, direction);
} catch(exception) {
console.error(`カーソルの生成に失敗しました。`);
}
if(cursorRequest !== null) {
//カーソルによるオブジェクトストア操作箇所の始まり
let r = new Array();
let count = 0;
cursorRequest.addEventListener('success', (event)=>{
const cursor = event.target.result;
if(cursor === null){
console.log(`カーソルの移動が終了しました。`);
if(count === 0) console.error(`対象となるレコードがありませんでした。`);
else {
console.log(`カーソルの移動が終了しました。_全移動回数_>${count}`);
console.dir(event.target.source);
console.dir(r);
}
} else {
console.log(`カーソルの移動は_>${count}回めです。`);
console.log(`カーソルリクエストを参照_>${cursor.request}`);
r.push(cursor.value);
try {
cursor.advance(cursorStep);
} catch(exception) {
console.error(`カーソルの移動に失敗しました。`);
console.dir(exception);
}
count++;
}
}, false);
cursorRequest.addEventListener('error', (event)=>{
console.error(`カーソルの移動の_>${count}回めを失敗しました。`);
}, false);
//カーソルによるオブジェクトストア操作箇所の終わり
}
長いですね。
でも、(その15)と異なるのは、つぎのインデックスオブジェクからカーソルオブジェクト生成して階層を一段潜るくだりだけです。
let cursorRequest = null;
try {
//インデックスキー(補キー)のカーソルを生成する。
cursorRequest = indexObject.openCursor(range, direction);
} catch(exception) {
console.error(`カーソルの生成に失敗しました。`);
}
if(cursorRequest !== null) {
//カーソルによるオブジェクトストア操作箇所の始まり
//カーソル処理
//カーソルによるオブジェクトストア操作箇所の終わり
}
インデックスキー(補キー)ではインデックスオブジェクトのopenCursorメソッド(IDBIndexのインスタンスメソッドです。)を使います。
パラメータについてもストアオブジェクトのopenCursorメソッド(IDBObjectStoreのインスタンスメソッドです。)と同じです。
生成にあたり例外の発生することもありますからtry文で包みます。
例の如く、階層を深くしたくないので、先に「let cursorRequest = null;」を宣言して、無事にカーソル生成がされればカーソル処理を行うようになっています。
そして、「//カーソル処理」の部分は(その15)からコピペしてあるばかりなので、そちらの説明をご覧ください。
「レコード取得」の説明はここまでです。
つぎはレコードのキー値の取得です。
(その15)ではプライマリキー(主キー)の値に限りましたが、今回はインデックスキー(補キー)とプライマリキー(主キー)の値を一緒に取得します。
コピペコードファイルの「カーソル移動:インデックスキー(補キー)’attributeArray’によるインデックスキー(補キー)値とレコードのプライマリキー(主キー)値の取得」を実行しますが…。
さきに「//インデックスキー(補キー)のカーソルを生成する。」のopenCursorメソッドがopenKeyCursorメソッド(IDBIndexオブジェクトのインスタンスメソッドです。)に変更されていることを確認してください。。
//インデックスキー(補キー)のカーソルを生成する。
cursorRequest = indexObject.openKeyCursor(range, direction);
実行します。
無事に実行できました。
(その15)では「r.push(cursor.value);」を「r.push(cursor.key);」に差し替えただけでしたが、今回はつぎのように記述してます。
r.push({KEY:cursor.key, PRIMARY_KEY:cursor.primaryKey});
今回は、「cursor.key」で参照できるのはインデックスキー(補キー)の値です。プライマリキー(主キー)の値は「cursor.primaryKey」で確認できます。
コンソールで判別しやすいように連想配列にて取得しました。
(注意)もちろんプライマリキー(主キー)の場合でも「cursor.primaryKey」は有効です。同じ値が返ってくるだけですが…。
次回は順番通りに、カーソル移動にによるレコードの削除と更新を紹介します。
最後に近づいてっくると、以前の投稿内容の不十分が気になります。検証と開発の進行の中、IndexedDB APIへの俯瞰もままならなかったので致し方ないでしょう。追記や訂正が多くなって申し訳ない。そかさ。