IndexedDBにはまってます。(その23)

最初に閑話です。

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}});
アプリケーション画面の「attributeArray」項目

(注意)順番が変更になってます。ごめんなさい。

(その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への俯瞰もままならなかったので致し方ないでしょう。追記や訂正が多くなって申し訳ない。そかさ。