クモのようにコツコツと

フロントエンドエンジニア イイダリョウの技術ブログ。略称「クモコツ」

【擬似NoSQL】ターミナルからAPIモックのJSON ServerにCRUDする

DB操作の続きです。前回はMAMPのMySQLをターミナルから操作しました。今回はAPIモックのJSON Serverにトライします。JSONデータをDBとして使うNoSQLライクなCRUD体験。curlコマンドを使ってターミナルから操作します。それではいきましょう!

【目次】

※参考:前回記事
【SQL】ターミナルからMAMPのMySQLにCRUDする - クモのようにコツコツと

※参考:Web開発環境についてのまとめ
qiita.com

前回のおさらい:MySQLをCRUD!

前回は、MAMPのMySQLのデータをphpMyAdminではなくターミナルからCRUDした。

f:id:idr_zz:20200802183554j:plain

CRUDはデータベースの基本4操作でデータの追加、取得、更新、削除。SQL文では下記に相当する。

CRUD SQL文 機能
Create INSERT文 データを追加
Read SELECT文 データを取得
Update UPDATE文 データを更新
Delete ETE文 データを削除

※参考:前回記事
【SQL】ターミナルからMAMPのMySQLにCRUDする - クモのようにコツコツと

NoSQL:SQL(RDB)じゃない方DB

DBには他にNoSQLというものもある。NoSQLはSQL(RDB)以外のデータベースの総称。

NoSQL(一般に "Not only SQL" と解釈される)とは、関係データベース管理システム (RDBMS) 以外のデータベース管理システムを指すおおまかな分類語である。

※参考:NoSQL - Wikipedia

下記の図のように色々な種類がある。

f:id:idr_zz:20200803080059j:plain

※参考:KVS系NoSQLのまとめ(Hibari、Dynamo、Voldemort、Riak編) (1/4):知らないなんて言えないNoSQLまとめ(1) - @IT

こちらのDBの歴史の記事にRDBやNoSQLが生まれた経緯がわかりやすく解説されている!

※参考:RDBとNoSQLにみるDB近現代史 データベースに破壊的イノベーションは二度起きるか? - エンジニアHub|若手Webエンジニアのキャリアを考える!

MongoDB:JSONライクなDB

NoSQLの中でも代表的なのが「MongoDB」。JSONライクな「ドキュメント指向」のデータベース。

 {
    "username" : "bob",
    "address" : {
        "street" : "123 Main Street",
        "city" : "Springfield",
        "state" : "NY"
    }
}

※参考:MongoDB - Wikipedia

JSONライクっつーか、JSONそのものやないか〜い(チーン♪)←ワイングラスで乾杯する音

RDBとMogoDBの呼称の違い。結構違うね。

No RDBでの呼称 MongoDBでの呼称
1 database database
2 table collection
3 row document
4 column field
5 index index
6 primary key _id

※参考:【MongoDB】初めてでも分かる!MongoDB入門(前編) | ヘッドウォータースのブログ TechNote

MogoDBのCRUD操作の書き方はJSライクで読みやすそう。部分的にSQL文と共通する名称がある。

CRUD MongoDB SQL文 機能
Create insert() INSERT文 データを追加
Read find() SELECT文 データを取得
Update update() UPDATE文 データを更新
Delete remove() DELETE文 データを削除

※参考:【MongoDB】初めてでも分かる!MongoDB入門(後編) | ヘッドウォータースのブログ TechNote

JSON Server:JSONファイルをDBにできるモックAPI

MongDBはJSONライクなDBだが、「JSON Server」ならなんと、JSONファイルそのものがDBになって、CRUDできる!

JSON ServerはNode.jsから提供されている「APIモック」環境。

※参考:GitHub - typicode/json-server: Get a full fake REST API with zero coding in less than 30 seconds (seriously)

「API」についてはこちらも参照

※参考:REST APIとは何かを調べまくったらようやくイメージができてきたのでまとめた - クモのようにコツコツと

「モック」とはモックアップの略でプロトタイプ(模型)といった意味合い。

※参考:https://wa3.i-3-i.info/word1437.html

フロントエンド開発時にバックエンド側のAPIがまだ完成しない場合、このJSON ServeでAPIテストできるようだ。


JSON Server実際に使ってみる。下記の記事を参考にさせていただいた。

※参考:たった30秒でREST APIのモックが作れる JSON Serverでフロントエンド開発が捗る – WPJ

※参考:CentOSへJSON Serverをインストール - Qiita

※参考:APIのモックアップに便利なjson-server使ってみた。 - かもメモ

※参考:JSON Serverで作るダミーAPI - to-R Media

JSON Serverインストール→db.json作成

まずはJSON Serverをグローバル環境にインストールする。

npm install -g json-server

「jsonServer」というフォルダを作りその中に「db.json」というファイルを作る。

前回のMySQLと同じビートルズのメンバーリストを作りたい。

{
    "beatles": []
}
  • 連想配列beatlesキーの値を配列にする

RDBは最初にテーブルのカラム名の設定したがNoSQLは設定不要。データ追加時に直接キー名(フィールド)を値と一緒に送信する。


このときちょっとハマったのだが、JSON Serverは仕様の縛りとして階層構造にできないようだ。

json-serverの制約としてリソースパスにスラッシュを含めることが出来ない
具体的に言うとaccounts/campaigns のようなパスが設定出来ない
モックで作りたい場合はパスを書き換えて1階層で完結できるように対応する必要がある

※参考:json serverでAPIモックを自由自在に操る - notebook

前回のMySQLと同様にbeatles/member/の様な階層構造にしたらうまく動かなかった。うーむ、残念…

{
    "beatles": {
        "member": []
    }
}

なお、Expressを使ってなんとかする方法もある模様。

※参考:JSON Serverのおしいところをなんとかしたい | CYOKODOG

JSON Serverを起動

ターミナルのcdコマンドでフォルダに移動

cd /(パス)/jsonServer

JSON Serverの起動

json-server --watch db.json

実行結果

 \{^_^}/ hi!

  Loading db.json
  Done

  Resources
  http://localhost:3000/beatles

  Home
  http://localhost:3000

  Type s + enter at any time to create a snapshot of the database
  Watching...

「ハイ!」と笑顔で声かけられたw


なお、ポート番号の初期値は3000だがサーバ起動時に--portオプションを加えると変更できるようだ。

json-server --watch db.json --port 8888

例えばこのように書くと下記のURLになる。

http://localhost:8888

他のツールのローカルサーバとポート番号が重複するときに使う。


ローカルホストのポート3000をブラウザで開くと

http://localhost:3000/

JSON Serverが起動している!「beatles」のリンクがある! f:id:idr_zz:20200804052604j:plain

「beatles」リンクを開くと…

http://localhost:3000/beatles

配列の器だけが表示された。中身はまだないw
f:id:idr_zz:20200804072844j:plain

これからデータの中身を追加していく!

curlコマンド(データの送受信)

ここからJSON ServerのCRUD処理に入っていきたい。JSON ServerはRDBではないのでSQL文は使えない。

どうやらLinuxコマンドの一つcurlを使って実現できるらしい。データの送信、受信を行うメソッド 。

※参考:【 curl 】コマンド――さまざまなプロトコルでファイルをダウンロード(転送)する:Linux基本コマンドTips(25) - @IT

※参考:【curl】超入門(GET/POST/PUT/DELETEでリクエスト)[LINUX] - Qiita

※参考:curl コマンド 使い方メモ - Qiita

オプション設定がいろいろあるが、今回はその中でも-xオプションを使う。プロキシ経由のアクセスができる。

curl -x

※参考:よく使うcurlコマンドのオプション - Qiita

「プロキシ」って自分はいまいち理解できてないのだが調べてみると…

ホームページを見るときに使うソフト(Webブラウザ)の身代わりになってホームページにアクセスしてくれるコンピュータ(サーバ)のこと

※参考:https://wa3.i-3-i.info/word1752.html

ふむ、確かにこのイメージはあったな。Webサイトに直接アクセスしないために間にかます的な。

プロキシ(Proxy)とは「代理」の意味である。インターネット関連で用いられる場合は、特に内部ネットワークからインターネット接続を行う際、高速なアクセスや安全な通信などを確保するための中継サーバ「プロキシサーバ」を指す。

※参考:プロキシ - Wikipedia

あーなるほど、「内部ネットワークからインターネット接続」。これが今回の用途に当たりそう。ブラウザではなくターミナルから接続するからプロキシを使う、ということかな。

curl + HTTPメソッド(POST、GET、PUT、DELETE)

JSON ServerのCRUD処理の書き方はこの様になる。

CRUD JSON Server SQL文 機能
Create curl -x POST INSERT文 データを追加
Read curl -x GET SELECT文 データを取得
Update curl -x PUT UPDATE文 データを更新
Delete curl -x DELETE DELETE文 データを削除

お、この-xオプションの後ろに続く処理名はHTTPメソッドだ!これはわかりやすいなー。

HTTPメソッドはいろいろな種類があるが…

※参考:HTTP リクエストメソッド - HTTP | MDN

Web開発でよく使われるのはPOST、GET、PUT、DELETEの4つ!まさにCRUD処理ですな。

※参考:Web開発でよく使う4つのHTTPメソッド【REST API】 | Web白熱教室

ちなみにhtmlのフォームでは今のところPOST、GETしか使えない。

※参考:なぜ html の form は PUT / DELETE をサポートしないのか? - Block Rockin’ Codes


ここでちょっとハマったのだが、これまで開いていたターミナルはローカルサーバを起動中のため、curlコマンドが打っても何も反応しないじゃないか!

かといって「Contrrl + C」でサーバを閉じると当然curlコマンドでサーバにアクセスできない。どうすりゃええのんか?

調べたところ、こちらはRubyの事例だが別のターミナルを開くことでコマンドが打てると!

別のコマンドを実行する方法としては、

  • Ctrl-C を押して、 Rails サーバを停止させてから 新しいコマンドを実行する
  • 別のターミナルウィンドウを開いて、そちらで、コマンドを実行する

※参考:Ruby - Railsサーバ接続後何もできない|teratail

別のターミナルを開いてcdコマンドで該当フォルダに移動。

cd /(パス)/jsonServer

これでコマンドを打てるようになった♪

Create:データの追加(curl -x POST)

まず、データの追加からしてみる。curl -X POSTを使う。

前回同様、まずはリーダのジョン・レノンから。

curl -X POST http://localhost:3000/beatles -d 'name=ジョン・レノン&part=ギター'

URLの後に-dオプションを使う。クエリ・パラメータの様な形式でPOSTリクエストを送ることができる。

※参考:よく使うcurlコマンドのオプション - Qiita

JSON Serverのブラウザ表示を確認するとデータが増えている! f:id:idr_zz:20200804073802j:plain
namepartしか追加してないが、自動的にid番号が追加されている。

続いてポールも追加してみる。

curl -X POST http://localhost:3000/beatles -d 'name=ポール・マッカートニー&part=ギター'

ジョージも。

curl -X POST http://localhost:3000/beatles -d 'name=ジョージ・ハリスン&part=ギター'

おお、JSON Serverに反映されてる!
f:id:idr_zz:20200804080022j:plain
クオリーメン生え抜きメンバーが揃った♪id番号も自動で振られている。

一度に二人分、POST送信できるだろうか?スチュとピートを追加してみる。

curl -X POST http://localhost:3000/beatles -d 'name=スチュアート・サトクリフ&part=ベース'
curl -X POST http://localhost:3000/beatles -d 'name=ピート・ベスト&part=ドラム'

JSON Serverの表示
f:id:idr_zz:20200804080345j:plain
ハンブルグ巡業のフルメンバーが揃った!

Read:データの取得(curl -x GET)

次にReadを行う。curl -X GETを使う。

curl -X GET http://localhost:3000/beatles

おお、ターミナル内でもDBの中身をみることができた!

[
  {
    "name": "ジョン・レノン",
    "part": "ギター",
    "id": 1
  },
  {
    "name": "ポール・マッカートニー",
    "part": "ギター",
    "id": 2
  },
  {
    "name": "ジョージ・ハリスン",
    "part": "ギター",
    "id": 3
  },
  {
    "name": "スチュアート・サトクリフ",
    "part": "ベース",
    "id": 4
  },
  {
    "name": "ピート・ベスト",
    "part": "ドラム",
    "id": 5
  }
]

/1を追記すると

curl -X GET http://localhost:3000/beatles/1

配列の1番目のデータのみが表示された!

{
  "name": "ジョン・レノン",
  "part": "ギター",
  "id": 1
}

さらに/nameを追加するとどうなるか?

curl -X GET http://localhost:3000/beatles/1/name

うーむ、表示されない。

{}

期待してたレスポンスは"ジョン・レノン"だったのだが、やはり先ほどの「階層管理できない」と同じ仕様上の制限のようだ。。

Update:データの更新(curl -x PUT)

次はデータの更新、curl -x PUTを使う。

ポールのパートをベースに変更。スチュが美術方面に専念するため。

curl -X PUT http://localhost:3000/beatles/2 -d 'name=ポール・マッカートニー&part=ベース'

GET送信で結果を確認

curl -X GET http://localhost:3000/beatles/2

実行結果、ベースになった!

{
  "name": "ポール・マッカートニー",
  "part": "ベース",
  "id": 2
}

ちなみにこちらは失敗例。最初に変更点であるpartのパラメータのみを送信したところ…

curl -X PUT http://localhost:3000/beatles/2 -d 'part=ベース'

nameが消えてしまった。。

{
  "part": "ベース",
  "id": 2
}

全てのパラメータを送らないとそのキーは削除された、と認識されるようだ(idは不要だが)

Delete:データの削除(curl -x DELETE)

最後にデータの削除を行う。curl -x DELETEを使う。

まず、スチュが脱退する。id番号(4)で指定する。

curl -X DELETE http://localhost:3000/beatles/4

GET送信で結果を確認

curl -X GET http://localhost:3000/beatles

実行結果、スチュが脱退した!

[
  {
    "name": "ジョン・レノン",
    "part": "ギター",
    "id": 1
  },
  {
    "name": "ポール・マッカートニー",
    "part": "ベース",
    "id": 2
  },
  {
    "name": "ジョージ・ハリスン",
    "part": "ギター",
    "id": 3
  },
  {
    "name": "ピート・ベスト",
    "part": "ドラム",
    "id": 5
  }
]

次にピートも脱退する。id番号は5。

curl -X DELETE http://localhost:3000/beatles/5

GET送信で結果を確認

curl -X GET http://localhost:3000/beatles

実行結果、クオーリメン生え抜きメンバーに戻った。

[
  {
    "name": "ジョン・レノン",
    "part": "ギター",
    "id": 1
  },
  {
    "name": "ポール・マッカートニー",
    "part": "ベース",
    "id": 2
  },
  {
    "name": "ジョージ・ハリスン",
    "part": "ギター",
    "id": 3
  }
]

最後のワンピース、POST送信でリンゴを加入させる!

curl -X POST http://localhost:3000/beatles -d 'name=リンゴ・スター&part=ドラム'

GET送信で結果を確認

curl -X GET http://localhost:3000/beatles

実行結果、デビュー時のフルメンバーに!

[
  {
    "name": "ジョン・レノン",
    "part": "ギター",
    "id": 1
  },
  {
    "name": "ポール・マッカートニー",
    "part": "ベース",
    "id": 2
  },
  {
    "name": "ジョージ・ハリスン",
    "part": "ギター",
    "id": 3
  },
  {
    "name": "リンゴ・スター",
    "part": "ドラム",
    "id": 4
  }

前回のMySQLのidは削除分が欠番になり、リンゴは「6」だった。JSON Serverでは削除分の番号が詰まってリンゴのidは「4」になっている。これぞファブ・フォー!

ブラウザのJSON Serverもリアルタイムに変更が反映されている。 f:id:idr_zz:20200804183150j:plain

最後に「Contrl + C」でサーバを閉じる。

最後に

f:id:idr_zz:20200804183637j:plain

ということで今回はJSON Serverを使ってJSONファイルをDBライクにCRUDしました。

DBについてはRDBとNoSQLを比較するとRDBの方が主流だと聞きます。ただ、シンプルなデータ構成であればどちらも同じことができるとわかりました。

また、DBがRDBにしろNoSQLにしろ、API通信時はJSON形式でデータをやりとりをすると思います。そういう意味ではJSON ServerはAP送受信時と同じ形で見れるのでわかりやすさを感じました♪

次回は、このJSON Serverに対してFetch APIを使ってフロントエンド側からCRUD処理にトライする予定です。

(2020/08/06追記)
予定を変えてNoSQLのデーターベスMongoDBでCRUDしました!

※参考:【NoSQL】ターミナルからMongoDBにCRUDする(JS & JSONライク!) - クモのようにコツコツと

それではまた!


※参考:Web開発環境についてのまとめ
qiita.com