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

その都度、複数のインデックスキー(補キー)を登録・追加登録・削除する用に指定項目の配列を登録して進めます。

まずは登録用配列です。つぎのコードを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}
];
コンソールに登録されたインデックスキー(補キー)指定用の配列

先に(その19)の、オブジェクトストア生成とインデックスキー(補キー)登録を済ませます。

今回もコピペコード全てをテキストファイル「code_IndexedDB_20.txt.zip」にまとめてアップロードしました。ご利用ください。

オブジェクトストアと登録されたインデックスキー(補キー)

まずはインデックスキー(補キー)の追加登録を紹介します。

当たり前ですが、すでに生成されたオブジェクトストアに対してインデックスキー(補キー)を追加登録するのでcreateObjectStoreメソッドは使いません。

既存オブジェクトストアを参照するがため、今までコメントにしておいた四行目の「//const tx = event.target.transaction;」をソースコードに戻して、トランザクションの中からオブジェクトストアを引っ張り出しすようにして処理を進めます。

よって、いままでのアップグレードイベントの発火受け取り枠とは、少々概念が異なります。

先につぎの追加登録用配列を登録してから、その下のコードをWebブラウザのコンソールにコピー&ペーストし、エンターキーで実行します。コードの説明は後です。

(注意)一行目の「indexedDB.open(‘DB_name’, 2);」を確認してください。openメソッドの第二パラメータが「2」になってます。’DB_name’のアップグレードイベントを発火させるためにバージョンアップしています。

const storeIndex = [
	{name:'author', path:'author', unique:false, me:false},
	{name:'indexArray', path:['index.en','id'], unique:false, me:false},
	{name:'tagMulti', path:'tag', unique:false, multi:true}
];
const openRequest = indexedDB.open('DB_name', 2);
openRequest.addEventListener('upgradeneeded', (event) => {
	const db = event.target.result;
	const tx = event.target.transaction;
	console.log(`UPGRADE_DB_VER_>${db.version}_OLD_>${event.oldVersion}_NEW_>${event.newVersion}`);

	//今回の主題は次のブロックになります。
	try {
		const objectStore = tx.objectStore('Store_name');
		//インデックスキー(補キー)を追加登録する。
		storeIndex.forEach((v, i, a) => {
			try {
				objectStore.createIndex(v.name, v.path, {unique:v.unique, multiEntry:v.multi});
			} catch(exception) {
				console.error(`インデックスキー(補キー)の追加登録に例外が発生しました。_>${exception.message}`);
			}
		});
		objectStore.transaction.addEventListener('complete', (event)=>{console.log(`インデックスキーの追加登録に成功しました。`);}, false);
		objectStore.transaction.addEventListener('abort', (event)=>{console.error(`トランザクションが中断しました。`);}, false);
		objectStore.transaction.addEventListener('error', (event)=>{console.error(`トランザクションでエラーが発生しました。`);}, false);
	} catch(exception) {
		console.error(`例外が発生しました。_>${exception.message}`);
	}

}, false);
openRequest.addEventListener('success', (event)=>{
	const db = event.target.result;
	console.log(`データベースを開始しました。`);
	db.close();
	db.addEventListener('close', ()=>{console.log(`データベースが閉鎖されました。`);}, false);
}, false);
openRequest.addEventListener('error', (event)=>{console.error(`データベースの開始に失敗しました。`);}, false);
コンソール画面の入力と結果表示
データベースDB_nameのバージョンは「2」
オブジェクトストアにインデックスキー(補キー)が追加登録される。

インデックスキー(補キー)が追加登録されました。コードの説明をします。

先にも記述した通り、定数txでトランザクションを代入して参照できるようにしてます。これを利用して「//今回の主題は次のブロックになります。」につづきます。

その定数txのobjectStoreメソッドを使って、定数objectStoreにオブジェクトストアを代入します。(メソッド名と定数名が同じなので気をつけてください。)objectStoreメソッドは例外が発生しますのでtry文で包みます。

つづいて「//インデックスキー(補キー)を追加登録する。」のくだりは、(その19)の「//インデックスキー(補キー)を登録する。」と同じことになります。

createIndexメソッドを使うのも、そのパラメータも同じです。

コードの構造としては(その19)のオブジェクトストア生成時のインデックスキー(補キー)登録と変わりありませんが、トランザクションから既存のオブジェクトストアを取得しているという大きな違いがあります。

この例では、インデックスキー(補キー)が配列で登録されていることも確認できます。

なお、インデックスキー(補キー)の名前が既存と同じでは登録ができません。例外が返ってきて当該インデックスキー(補キー)だけが蹴られます。

配列にある他のキーは登録されてしまい、処理全体がキャンセルされるわけではないので注意が必要です。

(注意)検証するときにデータベースをバージョンアップすることをお忘れなく。自戒を込めて。

つづいてインデックスキー(補キー)の削除を紹介します。

コードの構造と操作は追加登録とほぼ同じで、createIndexメソッドではなくてdeleteIndexメソッドを使います。パラメータはインデックスキー(補キー)の名前だけです。

つぎの削除用配列を登録してから、その下のコードを実行します。

(注意)一行目のopenメソッドの第二パラメータが「3」になっていることを確認してください。

const storeIndex = [
	{name:'indexEn'},
	{name:'author'},
	{name:'id'}
];
const openRequest = indexedDB.open('DB_name', 3);
openRequest.addEventListener('upgradeneeded', (event) => {
	const db = event.target.result;
	const tx = event.target.transaction;
	console.log(`UPGRADE_DB_VER_>${db.version}_OLD_>${event.oldVersion}_NEW_>${event.newVersion}`);

	//今回の主題は次のブロックになります。
	try {
		const objectStore = tx.objectStore('Store_name');
		//インデックスキー(補キー)を削除する。
		storeIndex.forEach((v, i, a) => {
			try {
				objectStore.deleteIndex(v.name);
			} catch(exception) {
				console.error(`インデックスキー(補キー)の削除に例外が発生しました。_>${exception.message}`);
			}
		});
		objectStore.transaction.addEventListener('complete', (event)=>{console.log(`インデックスキーの削除に成功しました。`);}, false);
		objectStore.transaction.addEventListener('abort', (event)=>{console.error(`トランザクションが中断しました。`);}, false);
		objectStore.transaction.addEventListener('error', (event)=>{console.error(`トランザクションでエラーが発生しました。`);}, false);
	} catch(exception) {
		console.error(`例外が発生しました。_>${exception.message}`);
	}

}, false);
openRequest.addEventListener('success', (event)=>{
	const db = event.target.result;
	console.log(`データベースを開始しました。`);
	db.close();
	db.addEventListener('close', ()=>{console.log(`データベースが閉鎖されました。`);}, false);
}, false);
openRequest.addEventListener('error', (event)=>{console.error(`データベースの開始に失敗しました。`);}, false);
コンソール画面の入力と結果表示
オブジェクトストアのインデックスキー(補キー)が削除される。

キーが減っていることを確認できます。

インデックスキー(補キー)の追加登録と削除でした。

つぎからは、インデックスキー(補キー)の利用になります。データベースのアップデートイベントではなく、開始成功イベントの発火受け取り枠に舞台が戻ります。

プライマリキー(主キー)と同様にカーソル運用の有る無しで記述が異なります。処理もワンステップ増える印象ですが、プライマリキー(主キー)でのことを把握していれば難しくはないでしょう。

ようやくダンジョンの最下層の入り口に辿り着いた気分です。そかさ。