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

IndexedDBにはまってます。(その23)で、インデックスキー(補キー)の場合のカーソルの移動によるレコードとキーの参照(取得)を紹介しました。

今回は(その17)(その18)と同様に、deleteメソッドによるレコードの削除と、updateメソッドによる更新を一気に紹介します。(どちらもIDBCursorのインスタンスメソッドです。)

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

前回同様に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}}
];
オブジェクトストアに格納されたレコード

そしてラングオブジェクト生成メソッドも準備します。

コピペコードファイルの「ラングオブジェクトを生成するメソッド」を登録します。

(その23)とコードの構造は同様です。注意事項を確認します。

レコードの削除(更新も)ですから、トランザクションの生成は’readwrite’モードです。

const tx = db.transaction('Store_name', 'readwrite');

インデックスオブジェクトのカーソル移動は、マルチエントリーを真にしたインデックスキー(補キー)’tagMulti’を対象とします。

indexObject = objectStore.index('tagMulti');

ラングオブジェクトの生成指定は(その22)の最後尾の検証と同じく配列要素に’jewelry’があるレコードとします。

const range = newRange({start:{v:'jewelry', b:false}, end:{v:'jewelry', b:false}});

確認まで「//インデックスキー(補キー)のカーソルを生成する。」ではopenCursorメソッド(IDBIndexのインスタンスメソッドです。)を利用します。

//インデックスキー(補キー)のカーソルを生成する。
cursorRequest = indexObject.openCursor(range, direction);

あとはカーソルオブジェクトの生成すれば、やっぱり(その23)と同じく、一段階層が深くなるだけで(その17)からのコピペで済みました。つぎです。

//操作前のレコードを取得する。
r.push(JSON.parse(JSON.stringify(cursor.value)));
let req = null;
try {
	req = cursor.delete();
	req.addEventListener('success', (event)=>{
		console.log(`レコードの削除に成功しました。`);
	}, false);
	req.addEventListener('error', (event)=>{
		console. error(`レコードの削除に失敗しました。`);
	}, false);
} catch(exception) {
	console.error(`カーソルによる操作に失敗しました。`);
	console.dir(exception);
}
if(req !== null) {
	try {
		cursor.advance(cursorStep);
	} catch(exception) {
		console.error(`カーソルの移動に失敗しました。`);
		console.dir(exception);
	}
	count++;
}

留意点としては、JSONのメソッドを使って「//操作前のレコードを取得する。」(試験的バックアップです。)こと、

r.push(JSON.parse(JSON.stringify(cursor.value)));

カーソルオブジェクトのdeleteメソッドを利用することです。

req = cursor.delete();

同じ説明をすることもないので、(その17)で確認してください。

それでは、コピペコードファイルの「カーソル移動:インデックスキー(補キー)’tagMulti’によるレコードの削除」を実行します。

アプリケーション画面の「tagMulti」項目(削除前)
コンソール画面の入力と結果表示
アプリケーション画面の「tagMulti」項目(削除後)

目的のレコードが削除されています。(ごそっと消えるのでよく確認しましょう。)

つづけてカーソル移動によるレコードの更新を紹介します。

レコードの格納状態を復旧しますので、つぎと同じ、コピペコードファイルの「レコードの配列(復旧用)」をコンソールに登録して、「レコードの格納」を実行し、最初のレコード格納状態に戻します。

const records = [
	{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}},
];

ここまで削除と同様の準備ですから、最初からやり直しても大丈夫です。

そしたら先に、コピペコードファイルから「レコードの配列(更新用)」を利用して、コンソールに更新用のレコード配列を登録します。

const records = [
	{key:[1, 'SN0003'], data:{index:{en:1, sn:'SN0003'}, title:'亜鉛'}},
	{key:[2, 'SN0001'], data:{index:{en:2, sn:'SN0001'}, title:'金'}},
	{key:[3, 'SN0002'], data:{index:{en:3, sn:'SN0002'}, title:'銀'}},
	{key:[4, 'SN0004'], data:{index:{en:4, sn:'SN0004'}, title:'プラチナ'}},
	{key:[5, 'SN0005'], data:{index:{en:5, sn:'SN0005'}, title:'銅'}},
	{key:[6, 'SN0006'], data:{index:{en:6, sn:'SN0006'}, title:'アルミニウム'}},
	{key:[7, 'SN0009'], data:{index:{en:7, sn:'SN0009'}, title:'錫'}},
	{key:[9, 'SN0011'], data:{index:{en:9, sn:'SN0011'}, title:'鉛'}}
];

この配列につては(その18)に説明があります。検証の手を抜くために少しややこしいことをしてますので、ご注意ください。

レコードの更新実行コードは、削除の場合と同様です。同じ位置に(その18)からコードのコピペで済みました。つぎのコードです。

//操作前のレコードを取得する。
r.push(JSON.parse(JSON.stringify(cursor.value)));
const upValue = cursor.value;
for(let i=0; i<records.length; i++) {
	//更新データのkeyとプライマリキー(主キー)の値を比較する。
	if(indexedDB.cmp(records[i].key, cursor.primaryKey) === 0) {
		const ks = Object.keys(records[i].data);
		for(let k of ks) {
			upValue[k] = records[i].data[k];
		}
		break;
	}
}
let req = null;
try {
	req = cursor.update(upValue);
	req.addEventListener('success', (event)=>{
		console.log(`レコードの更新に成功しました。`);
	}, false);
	req.addEventListener('error', (event)=>{
		console. error(`レコードの更新に失敗しました。`);
	}, false);
} catch(exception) {
	console.error(`カーソルによる操作に失敗しました。`);
	console.dir(exception);
}
if(req !== null) {
	try {
		cursor.advance(cursorStep);
	} catch(exception) {
		console.error(`カーソルの移動に失敗しました。`);
		console.dir(exception);
	}
	count++;
}

留意点は、JSONオブジェクトを使って「//操作前のレコードを取得する。」の実コードのつぎ、ここでは三行目からです。

移動中のカーソルが今現在抱えているレコードが、更新配列の中にあったらば、そのレコード内の情報を代入(変更)して、更新準備をするというものです。

更新配列の中に対象がなければ、レコードは現状のまま素通りします。

const upValue = cursor.value;
for(let i=0; i<records.length; i++) {
	//更新データのkeyとプライマリキー(主キー)の値を比較する。
	if(indexedDB.cmp(records[i].key, cursor.primaryKey) === 0) {
		const ks = Object.keys(records[i].data);
		for(let k of ks) {
			upValue[k] = records[i].data[k];
		}
		break;
	}
}

そして、削除のdeleteメソッド行をupdateメソッドに差し替えて、変更もしくは現状のレコードをパラメータにして、ともかく更新を実行してしまいます。

req = cursor.update(upValue);

詳しく同じ説明をすることもないので、(その18)でご確認ください。

それでは、コピペコードファイルの「カーソル移動:インデックスキー(補キー)’tagMulti’によるレコードの更新」を実行します。

コンソール画面の入力と結果表示
オブジェクトストアで更新されたレコード

目的のレコードのタイトルが日本語に代わりました。

よっしゃー。比較的短い文章で済みました。プライマリキー(主キー)の時の苦労が報われました。

これで、はまったシリーズはその紹介が一通り済みました。(とりま、自分を褒めたい。)

「しかしま、こんなに大掛かりなものをどうやって取り扱うの?」と、感想を持たれるやもしれません。

いやいや、私の駄文を根気よく読んでここまで到達したような強者(感謝。)であれば、そんな心配は不要なのかもしれません。

しかしながら、ばらばらの紹介をしたままでは少々気が引けます。

はまったシリーズ(まとめ)として、投稿しながら開発した独自手法の概略を紹介いたします。

参考になるのか甚だ不安ですが、まあ、今更ってところですか。そかさ。