見出し画像

Node For Max ③ ~MongoDBと接続する~

引き続き Node For Max 触ってます。
前回前々回と HTTP で別サービスと連携する記事を書きました。
今回はローカルに立ち上げたデータベースに接続して、データを取得するプログラムを書いてみます。
データベースの種類は何でもいいのですが、オブジェクト構造をそのまま扱える方が嬉しいので、MongoDB を利用します。


MongoDB とは

NoSQL のドキュメント指向データベースの一種です。表形式で表現できないようなデータを柔軟に扱えます。
オープンソースとして提供されていて、Docker Hub に公式のイメージも用意されています。
今回はこちらのイメージを使って、MongoDB のコンテナを立ち上げようと思います。

docker の話は今回できないので、興味ある方は調べてみてください。
MongoDB をローカル PC に直インストールでも問題ありません!

ゴール

MongoDB に保存した音源ファイル名を取得して、指定した音源を再生するプログラムを作成する。

音源とメタデータには、GDC Game Audio Bundles が無償で提供しているバンドルを利用しようと思います。

成果物はこちらです。

開発

MongoDBの用意

ローカルに直接インストールした方は、ここは無視してください。
node-for-max データベースとユーザーの作成だけしてください。

公式の docker イメージからビルドして、27017 ポートでアクセスできるようにします。docker-compose ファイルは下記の通りです。

version: "3.1"

services:
    mongo:
        image: mongo:6.0.8
        environment:
            MONGO_INITDB_DATABASE: node-for-max
            MONGO_INITDB_ROOT_USERNAME: node-for-max
            MONGO_INITDB_ROOT_PASSWORD: n4m
        ports:
            - 27017:27017

docker コンテナを立ち上げる

docker compose -p node-for-max-mongodb up -d

データの用意

GDCが音源リストをSpreadSheetで公開しているので、これをCSVで出力して、そのままMongoDBにインポートします。

fileName / libraryName / supplier のプロパティがありますね。

インポートした MongoDB のデータ

データ取得プロセス部分の開発

MongoDB の公式が Node.js 用のドライバーを提供してくれているので、こちらをインストールします。

MongoDB Node Driver

npm i --save mongodb
npm i --save-dev @types/mongodb

以下 2 つの機能を開発します。
①supplierの一覧取得
②指定したsupplierを条件に、ファイル名をMongoDBから取得

const main = async () => {
    // MongoDB と接続
    const manager = new MongoDBClientManager();
    const db = await manager.getDb();

    // gdcarchive コレクションから、supplier の一覧を取得
    const supplierList = await db.collection('gdcArchive').distinct('supplier', {});
    // Max の outlet から結果を出力
    MaxAPI.outlet(supplierList);

    // MongoDB 切断
    await manager.close();
}
const main = async () => {
    // MongoDB と接続
    const manager = new MongoDBClientManager();
    // Max の inlet から supplier 情報を取得して検索条件作成
    MaxAPI.addHandler(MaxAPIStatic.MESSAGE_TYPES.DICT, async (...args: {[key: string]: string | number | boolean}[]) => {
		const filter: Partial<Filter> = {};
        const filterSet = new Set(dataProperties);
        for (const [key, value] of Object.entries(args[0])) {
            if(filterSet.has(key)) Object.assign(filter, {[key]: value});
        }

        // gdcarchive コレクションから、指定した supplier の音源ファイル名を取得
        const db = await manager.getDb();
        const soundFiles = await db.collection('gdcArchive').fid(filter).toArray();
        const soundFilePathList: string[] = [];
        soundFiles.forEach(soundFile => {
            soundFilePathList.push(soundFile.fileName);
        });

        // 取得したファイル名を出力
        MaxAPI.outlet(soundFilePathList);
        await manager.close();
    });
}

Max の開発

Max の開発script start 後に、①のプロセスが supplier を取得してくれます。それをリスト形式表示しておきます。

リストからsupplierを選択すると②が実行されて、マッチするファイル名のリストが出力されます。
ファイル名リストから選択すると、指定した音源が読み込まれて再生されます。

※ 起動時に音源ファイルのパスを指定するウィンドウが開くので、ダウンロードしたディレクトリを選択してください。

おわりに

巨大なデータを読み込ませると OOM の危険性が上がるので、データは一旦データベースに持たせて、必要な分だけ読み込むといったことができますね。

Max も一応、配列だったり辞書型を扱えるけど、そういったオブジェクト操作はかなり苦手です。
UI のオブジェクトも充実しているところが Max のいいところですが、適材適所で責任分離したいです。

そのうち、音源リストの表示や選択部分を別アプリケーションに任せたバージョンを作ってみようと思います。

この記事が気に入ったらサポートをしてみませんか?