OSS版AirtableことNocoDBを触ってみた

本記事は[NECソリューションイノベータAdventCalendar 2022](https://qiita.com/advent-calendar/2022/nec_solution_innovators)の12/12の記事です。

## NocoDBとは

最近、Excelを扱う感覚でデータベースを管理できるノーコードツールが流行しており、海外ではAirtable、国内ではkintoneなどのクラウドサービスが人気です。NocoDBはこのAirtableのOSS版のソフトウェアになります。OSSといってもデータの管理のしやすさ、APIの自動作成などAirtableの基本機能を備えており、Githubのスターが3万以上ある人気ソフトウェアです。

参考まで公式の画像イメージを以下に記載します。
![https://user-images.githubusercontent.com/35857179/194844858-d353bd15-1edf-406c-889b-ba60f76831f4.png](https://user-images.githubusercontent.com/35857179/194844858-d353bd15-1edf-406c-889b-ba60f76831f4.png)

https://www.nocodb.com/

## NocoDBの利用ケース

私はWebアプリを開発する機会が多いのですが、データベースを作成しつつAPIが自動作成できるため、バックエンド開発を省力化できるという点で開発初期に作るようなプロトタイプ開発と相性がいいと感じています。またクラウドサービスと比較してNocoDBが優位と思ったケースです。

- 低コストが求められるケース
    - クラウドサービスは従量課金が多く、小さく始めることはできますが逆にデータや利用者が増えていくと費用が増えていくケースがあります。NocoDBは起動するマシンの費用は必要ですがそれ以外の費用が必要ありません。
- データの保存先をプライベートにしたいケース
    - クラウドサービス側も十分にセキュリティの考慮がされていますが、まだまだクラウド上に業務データを保存したり、インターネットを通じてアクセスできるという点が導入障壁になるケースがあります。NocoDBはイントラネットなどプライベートネットワークに構築することで経路を制限することができます。

## 試してみよう

Dockerで試してみたいと思います。nodeスクリプトなど他のパターンもあるみたいなので詳しくはこちらの公式ドキュメントを参考ください。

https://github.com/nocodb/nocodb/blob/develop/markdown/readme/languages/japanese.md

データベースには最近よく利用するMySQLを利用しました。MySQLとNocoDBを起動するdocker-compose.ymlは以下としました。

```yaml
version: '2.1'

services:
  root_db:
    platform: linux/x86_64
    image: mysql:latest
    volumes:
      - db_data:/var/lib/mysql
    command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: password
      MYSQL_DATABASE: root_db
      MYSQL_USER: noco
      MYSQL_PASSWORD: password
    ports:
      - "3306:3306"
    healthcheck:
      test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
      timeout: 20s
      retries: 10

  nocodb:
    depends_on:
      root_db:
        condition: service_healthy
    image: nocodb/nocodb:latest
    ports:
      - "8080:8080"
    restart: always
    volumes:
      - nc_data:/usr/app/data
    environment:
      NC_DB: "mysql2://root_db:3306?u=noco&p=password&d=root_db"
volumes:
  db_data: {}
  nc_data: {}
```

`docker-compose up -d` で起動したら、ブラウザから [http://localhost:8080/dashboard](http://localhost:8080/dashboard) にアクセスします。mysqlの起動タイミング次第でこけることがあるのでその場合はnocodbを再起動してください。

初回はサインアップ画面が表示されるので自分のアカウントを登録しましょう。
![Untitled (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/6d15cace-405f-f966-3123-466bf6177918.png)


登録後にホーム画面に遷移するので「NewProject」からプロジェクトを作成し、テーブルを作成してみます。
![Untitled (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/a331ec47-e52f-e6ae-4fba-71d297086770.png)

「test」というプロジェクトを作成します。
![Untitled (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/6140ccaf-d31e-0e69-9b50-f8c2ed1dfc02.png)


table1というテーブルを作成してみました。
![Untitled (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/034ce4ff-d089-4ee8-0a71-fcf636eb2480.png)

Title というカラムが最初からありますが、Author というカラムを追加してみます。
![Untitled (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/99c2845b-c089-6415-a8c3-a76080899e43.png)


試しにこのテーブルに2件ほどデータを登録してみました。
![Untitled (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/412bfc43-6c4b-49c1-6995-0094a873020c.png)

このときMySQLにはどういうデータが作成されているのか、mysqlコマンドで見てみます。

```
docker-compose exec root_db /bin/bash
bash-4.4# mysql -uroot -ppassword
```

databaseを root_db に切り替えてテーブル一覧を参照すると、NocoDBとして管理しているテーブルが大量に出力されました。その中に table1っぽいテーブルが存在しました。

```
mysql> use root_db
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+--------------------------------+
| Tables_in_root_db              |
+--------------------------------+
| nc_acl                         |
| nc_api_tokens                  |
| nc_audit                       |
| nc_audit_v2                    |
| nc_bases_v2                    |
| nc_col_formula_v2              |
| nc_col_lookup_v2               |
| nc_col_relations_v2            |
| nc_col_rollup_v2               |
| nc_col_select_options_v2       |
| nc_columns_v2                  |
| nc_cron                        |
| nc_d6br__table1                |　　<= これかな？
| nc_disabled_models_for_role    |
| nc_disabled_models_for_role_v2 |
| nc_evolutions                  |
```

試しにデータを参照しましたが合ってそうです。created_atやupdated_atなどはシステムとして自動的に作成されるカラムのようです。

```
mysql> select * from nc_d6br__table1;
+----+--------------+---------------------+---------------------+--------+
| id | title        | created_at          | updated_at          | Author |
+----+--------------+---------------------+---------------------+--------+
|  1 | Hello world1 | 2022-12-10 05:29:54 | 2022-12-10 05:29:58 | hoge   |
|  2 | Hello world2 | 2022-12-10 05:30:05 | 2022-12-10 05:30:08 | fuga   |
+----+--------------+---------------------+---------------------+--------+
2 rows in set (0.03 sec)
```

ついでにdescribeも叩いてみます。

```
mysql> describe nc_d6br__table1;
+------------+--------------+------+-----+-------------------+-----------------------------------------------+
| Field      | Type         | Null | Key | Default           | Extra                                         |
+------------+--------------+------+-----+-------------------+-----------------------------------------------+
| id         | int unsigned | NO   | PRI | NULL              | auto_increment                                |
| title      | varchar(45)  | YES  |     | NULL              |                                               |
| created_at | timestamp    | YES  |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED                             |
| updated_at | timestamp    | YES  |     | CURRENT_TIMESTAMP | DEFAULT_GENERATED on update CURRENT_TIMESTAMP |
| Author     | varchar(45)  | YES  |     | NULL              |                                               |
+------------+--------------+------+-----+-------------------+-----------------------------------------------+
5 rows in set (0.10 sec)
```

カラムの型はnocodbでカラムを追加するときのColumn Typeに依存しそうです。（Attachmentとかどうなるか気になりましたが今回はそこまで調べていません）
![Untitled (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/9b08c6fb-219b-8bd8-7333-e1db6495447c.png)

APIも試してみたいと思います。プロジェクトをクリックし、「Team & Settings」からトークンを発行します。
![Image 2022-12-10 15-26-22 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/8a032a8d-4dff-cc87-e66f-af0de78b23ae.png)
![Image 2022-12-10 15-28-02 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/62f81d29-86fc-32db-5f12-ef067136388a.png)

自動作成されるAPI情報(Swagger)はこちらから参照できます。
![Image 2022-12-10 15-29-56 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/d133e38b-733d-607b-ef72-9ab5567164b3.png)


swagger ui からトークンを設定し、table1のデータ一覧を実行した結果がこちらになります。
![Image 2022-12-10 15-32-42 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2277523/abe3becd-de9e-95c6-d741-8979459f4e87.png)


## 感想

Airtableのようにチャート生成機能やレコード単位のスナップショットなど高機能ではないですが、Excelのような操作性やAPI自動作成はシンプルながら強力なのでいろんなケースに利用できそうです。また、MySQLなど既存データベースを利用するため、本番運用のためにAPI+DBを作成しなおすという場合が発生してもDBは移行できる点がいいと思いました。不安な点としては、複雑なSQLが必要になるような場合や性能が求められるような場合には検証してみないと利用できるか判断ができないなと感じました。