技術情報

Electron-dbで一通りの操作をやってみる!

こんにちは、MSKです。
Json形式でデータを扱う「electron-db」というライブラリがあります。
今回は、electron-dbでデータの追加、取得、更新、削除と一通りの機能を試してみたいと思います。

準備

electron-dbをとりあえず使ってみた記事を以前書いたので、Electronのプロジェクトの準備、electron-dbのインストールは以下の記事を参考にして下さい。

Electronでデータベースを扱ってみる!Electronでデータベースを扱ってみます。 「electron-db」というライブラリを使います。...

機能を使ってみる

プロジェクトの準備ができましたら、早速試していきたいと思います。
試す時は上の記事と同じようにelectron-srcフォルダのindex.tsにipcMain.on()を書いて、レンダラープロセスでボタンを押すなどのイベントでメッセージ送って、それを受け取ることで、データベースの処理を行っています。
例えば、レンダラープロセスには次のようにボタンを用意して、クリックすることでメインプロセスにメッセージを送ります。

const clickGetAllButton = () => {
    global.ipcRenderer.send('db-get-all');
}
...
return (
  <Layout title="登録ページ">
    <h2>データ取得</h2>
    <button onClick={clickGetAllButton}>データ取得</button>
  </Layout>
)

メインプロセス側では受信したら、データベースの処理を行います。

ipcMain.on("db-get-all",(event: IpcMainEvent) => {
  let get_contents:test_read_object_t[]|boolean=getAllTestData();
  if("boolean" == typeof get_contents) {
    event.sender.send("db-get-all-resp",false);
  } else {
    event.sender.send("db-get-all-resp",get_contents);
  }
})

テーブルの作成

database.tsというファイルを作成します。
この中にデータベースの機能を書いていきます。
まずは、テーブルがない場合は作成する処理を書きます。

const db = require('electron-db');
const path = require('path');

const test_table_name:string = "TEST";
const save_path:string = path.join("./database","");

export const initDatabase = () : boolean => {
    let result:boolean = false;
    if(!db.tableExists(test_table_name,save_path)) {
        // テーブルが存在しないので作成
        db.createTable(test_table_name,save_path,(success:boolean, message:string) => {
            if(success) {
                console.log("createTable success : "+message);
                result = true;
            } else {
                console.log("createTable failed : "+message);
                result = false;
            }
        });
    } else {
        console.log("table already exists!");
        result = true;
    }
    return result;
}

プロジェクト直下にdatabaseフォルダをつくって、そこにファイルを作成するようにしています。
tableExists関数によってテーブルが存在するかどうかをチェックします。
存在しない場合はcreateTableによってテーブルを作成しています。

データの追加

まずtypes.tsというファイルを用意して、test_data_tというオブジェクトを作成します。
このオブジェクトをデータベースに保存するようにします。

export interface test_object_t {
    name: string,
    date: string,
    memo: string,
}

このオブジェクトをdatabase.tsでインポートしておきます。

次にdatabase.tsにデータを追加する関数を作成します。

export const createTestData = (create_data:test_object_t) : boolean => {
    let result : boolean = false;
    db.insertTableContent(test_table_name,save_path,create_data,(success:boolean,message:string) => {
        if(success){
            console.log("insertTableContent success : "+message);
            result = true;
        } else {
            console.log("insertTableContent failed : "+message);
            result = false;
        }
    });
    return result;
}

データを追加するにはinsertTableContentを使用します。
コールバックの第一引数がtrueなら、データ追加が成功しています。
保存したファイルを見ると次のようになっています。

{
  "TEST": [
    {
      "name": "MSK",
      "date": "2022/02/07 22:38",
      "memo": "memo1",
      "id": 1644241119506
    },
    {
      "name": "MSK",
      "date": "2022/02/07 22:38",
      "memo": "memo2",
      "id": 1644241132511
    }
  ]
}

データの取得

次に追加したデータを取得したいと思います。
データ取得のためのオブジェクトを用意したいと思います。

export interface test_read_object_t {
    name: string,
    date: string,
    memo: string,
    id:number,
}

最初に全てのデータを受信してみます。

export const getAllTestData = () : test_read_object_t[] | boolean => {
    let result : test_read_object_t[] | boolean = false;
    if(db.tableExists(test_table_name,save_path)) {
        //テーブルが存在するならgetAll
        db.getAll(test_table_name,save_path,(success:boolean,contents:test_read_object_t[]) => {
            if(success) {
                console.log("getAll success");
                console.log(contents);
                result = contents;
            } else {
                console.log("getAll failed");
                result = false;
            }
        });
    } else {
        console.log("table is not exist");
        result = false;
    }
    return result;
}

jsonファイルにある内容が取得できると思います。
最初にテーブルが存在するかを調べて、getAllでテーブルの全データを取得しています。

次にキーと値を指定して、検索を行いたいと思います。

export const getSpecifiedTestData = (date: string) : test_read_object_t[] | boolean => {
    let result : test_read_object_t[] | boolean = false;
    //テーブルが存在するか
    if(db.tableExists(test_table_name,save_path)) {
        db.getRows(test_table_name,save_path,{date: date},(success:boolean,contents:test_read_object_t[]) => {
            if(success) {
                console.log("getRows success : "+contents.length.toString());
                console.log(contents);
                if(contents.length > 0) {
                    result = contents;
                } else {
                    return false;
                }
                
            } else {
                console.log("getRows failed");
                result = false;
            }
        })
    } else {
        console.log("table is not exist");
        result = false;
    }
    return result;
}

getAllTestDataの時と同じようにテーブルが存在するかを調べて、存在するならgetRowsで第3引数で指定したキーと値に一致したデータを全て取得しています。
データがなくてもsuccess=trueで返ってくるため、データの個数を見て0個の場合はfalseを返しています。

getSpecifiedTestDataではキーと値が完全に一致している場合にデータを返してくれますが、あるキーの値が部分一致しているようなデータを取得したい場合にはsearchを使います。

export const searchTestData = (date: string) : test_read_object_t[] | boolean => {
    let result : test_read_object_t[] | boolean = false;
    //テーブルが存在するか
    if(db.tableExists(test_table_name,save_path)) {
        db.search(test_table_name,save_path,"date",date,(success:boolean,contents:test_read_object_t[]) => {
            if(success) {
                console.log("search success : "+contents.length.toString());
                console.log(contents);
                if(contents.length > 0) {
                    result = contents;
                } else {
                    return false;
                }
            } else {
                console.log("search failed");
                result = false;
            }
        })
    } else {
        console.log("table is not exist");
        result = false;
    }
    return result;
}

テーブルが存在するかを調べたあと、search関数を使っています。
第3引数にキー名を、第4引数に検索する文字列を指定します。
第3引数に指定したキーの値で、第4引数に指定した値が部分的にでも含まれているものがあるとそのデータ全てを取得します。
getRowと同様にデータがなくてもsuccess=trueで返ってくるので、データの個数をチェックしています。

データの更新

データの更新を行います。
今回はdateを指定して、その値に一致したデータのmemoのデータを更新します。

export const updateTestData = (date:string,memo:string) : boolean => {
    let result : boolean = false;
    //テーブルが存在するか
    if(db.tableExists(test_table_name,save_path)) {
        //dateが存在するかチェック
        db.getRows(test_table_name,save_path,{date:date},(success:boolean,contents:test_read_object_t[]) => {
            if(success) {
                console.log("updateTestData.getRows success.");
                console.log(contents);
                result = true;
            } else {
                console.log("updateTestData.getRows failed. "+date+" is not exist");
                result = false;
            }
        });
        //resultがtrueなら更新
        if(result) {
            db.updateRow(test_table_name,save_path,{"date":date},{"memo":memo},(success:boolean,message:string) => {
                if(success) {
                    console.log("updateTestData.updateRow success."+message);
                    result = true;
                } else {
                    console.log("updateTestData.updateRow failed."+message);
                    result = false;
                }
            });
        }
    } else {
        console.log("table is not exist");
        result = false;
    }
    return result;
}

テーブルが存在するか、指定したdateを持つデータはあるかを確認します。
その後にupdateRowによって、更新をかけます。
第3引数が更新対象として検索する値、第4引数がそのデータの更新する内容になっています。

データの削除

最後にデータの削除を行います。

export const deleteTestData = (date:string) : boolean => {
    let result : boolean = false;
    //テーブルが存在するか
    if(db.tableExists(test_table_name,save_path)) {
        db.deleteRow(test_table_name,save_path,{"date":date},(success:boolean,message:string) => {
            if(success) {
                console.log("deleteTestData.deleteRow success."+message);
                result = true;
            } else {
                console.log("deleteTestData.deleteRow failed."+message);
                result = false;
            }
        })
    } else {
        console.log("table is not exist");
        result = false;
    }
    return result; 
}

テーブルが存在するかを確認した後、deleteRowによって削除をかけます。
削除対象は第3引数で、削除するオブジェクトの対象となるキーと値を指定します。

electron-dbの簡易ドキュメント

自分用ですが、electron-dbのAPIについて簡単に説明をつけました。
参考にしていただけると嬉しいです。(説明がへたくそですみません・・・)

関数名機能引数コールバックの引数
(ない場合は戻り値)
createTableテーブル(json)ファイルを作成1. テーブル名
2. 保存場所(opt)
3. コールバック関数
[コールバック]
1. 結果
2. メッセージ
insertTableContentテーブルにデータを追加1. テーブル名
2. 保存場所 (opt)
3. 追加するデータ
4. コールバック関数
[コールバック]
1. 結果
2. メッセージ
getAllテーブルの全てのデータを読み込む1. テーブル名
2. 保存場所(opt)
3. コールバック関数
[コールバック]
1. 結果
2. 1により分岐
true → データ
false → メッセージ
getRows指定したキーと値に対応したデータを全て読み込む1. テーブル名
2. 保存場所(opt)
3. 検索条件
4. コールバック関数
[コールバック]
1. 結果
2. 1により分岐
true → データ
false → メッセージ
updateRow第2引数に対応したデータの全てを第3引数のキーに対応する値を第3引数の値に更新する1. テーブル名
2. 保存場所(opt)
3. 検索内容
4. 更新内容
5. コールバック関数
[コールバック]
1. 結果
2. メッセージ
search指定されたキーの値で、検索内容を含んでいるデータを読み込む1. テーブル名
2. 保存場所(opt)
3. キー
4. 検索内容
5. コールバック関数
[コールバック]
1. 結果
2. 1により分岐
true → データ
false → メッセージ または空のリスト
deleteRow 削除対象のキーと値を含んでいるデータを削除する1. テーブル名
2. 保存場所(opt)
3. 削除対象
4. コールバック関数
[コールバック]
1. 結果
2. メッセージ
valid適切なJSONファイルかチェック1. テーブル名
2. 保存場所 (opt)
[戻り値(boolean)]
true : 適切
false : 不適切
clearTableテーブルの内容をクリアして、空のリストのみにする1. テーブル名
2. 保存場所(opt)
3. コールバック関数
[コールバック]
1. 結果
2. メッセージ
getField指定したキーのデータを取得する1. テーブル名
2. 保存場所(opt)
3. キー/フィールド
4. コールバック関数
[コールバック]
1. 結果
2. 1により分岐
true → データ
false → メッセージ
countテーブルの中のデータ数を取得する 1. テーブル名
2. 保存場所(opt)
3. コールバック関数
[コールバック]
1. 結果
2. 1により分岐
true → データ数
false → メッセージ
tableExistsテーブルが存在するかチェックする1. テーブル名
2. 保存場所(opt)
[戻り値(boolean)]
true : 存在
false : 存在しない

(opt) とついている引数は省略可能。
省略した場合にはアプリケーションフォルダに保存されます。
(Widowsの場合は、C:\Users\[ユーザー名]\AppData\Roaming\[アプリ名])

最後に

今回はelectron-dbの一通りの操作について解説しました。
僕としては結構使いやすいので、今後作るアプリについてはelectron-dbを積極的に使ってみようかなと思います。

最後までご覧頂き、ありがとうございます。
「Electron-dbで一通りの操作をやってみる!」でした。

ABOUT ME
MSK
九州在住の組み込み系エンジニアです。 2児の父親でもあります。 数学やプログラミングが趣味です。 最近RustとReact、結び目理論と曲面結び目理論にはまっています。