- 投稿日:2020-03-14T23:01:57+09:00
Vue.jsプロジェクトのセットアップ
Vue.jsのプロジェクトを最初から作る手順を紹介します。
前提条件
- npm、yarnがインストール済みであること
@vue/cliのインストール
グローバルに@vue/cliをインストールしてvueコマンドを使用できるようにします。
$ npm install -g @vue/clivueプロジェクトの作成
$ vue create project-name
? Please pick a preset: (Use arrow keys) ❯ default (babel, eslint) Manually select features開発環境の起動
$ yarn serve
起動後、ブラウザからhttp://localhost:8080/で表示できます。
production用build
$ yarn build
成功すると、distディレクトリにファイルが作られます。
- 投稿日:2020-03-14T15:28:37+09:00
express-generatorでアプリを作成したらインストールするモジュール
- 投稿日:2020-03-14T15:28:37+09:00
express-generatorでアプリを作成したらする事
モジュール読み込むモジュール
- express-session
- express-validator
- mysql
- knex
- bookshelf
インストール方法
npm install --save モジュールapp.jsの追記
var bodyParser = require('body-parser'); var session = require('express-session'); var validator = require('express-validator'); app.use(validator()); var session_opt = { secret: 'keyboard cat', resave: false, saveUninitialized: false, cookie: {maxAge: 60 * 60 * 1000} }; app.use(session(session_opt));routesの中に新しくjsのファイルを追加する場合は、上記に追加して下記も追加する。
var hoge = require('./routes/追加したファイル名'); app.use('/パス名', hoge);※hoge、追加したファイル名、パス名は同じにすると分かりやすい
参考
node.js超入門 p376
- 投稿日:2020-03-14T15:18:39+09:00
3分で分かる。MERNスタックを簡単に説明してみる
MERNスタックの仕組みと、参考になるチュートリアルを提供する記事です。本当に重要な部分のみを扱いました。
MERNスタックとは
MongoDB, Express, React.js, Node.jsの4つを使ったソフトウェアハンドル。Webアプリ開発に用いられる。仮に、React.jsではなく、Angular.jsを使う場合、MEANスタックとなる。
MongoDB:ドキュメント志向のNo-SQLデータベース。データの保存などに使う。DBは、データベースの意。
ExpressJS:Node.jsのフレームワーク。Node.jsの機能と一緒に使う事で、バックエンドの構築が出来る。
ReactJS:単一ページWebアプリのUIを作成するUIコンポーネントを構築出来る。アプリケーションのView部分を担っている。
NodeJS:サーバーサイドでも動くjavascriptってカッコイイし楽だよね、と覚えておこう。何が良いのか
フルスタックエンジニアを名乗りたい人は、実はjavascriptが書ける時点で完結できてしまう。企業側から捉えると、サーバーサイドエンジニアの人手が足りなくても、開発案件がMERN構築で可能な場合、フロントエンドエンジニアをそのままサーバーサイドに。というアサインも可能かもしれない。
実際の中身
ユーザーは、アプリケーションのView(UI部分)と繋がっている。ReactとExpressはどちらもNode.jsで作成されている。この2つのコンポーネントは、RESTful APIを経由して通信している。
例)データを送信したいと思い、送信ボタンをクリックした場合:
クライアントPC
→ReactJSを経由
→NodeJSベースのExpressサーバーに送信
→MongoDBにいく。
例)データを取得したいと思い、ボタンをクリックした場合;
MongoDB
→NodeJSベースのExpressサーバーに送信
→ReactJSを経由
→クライアントPCにいく。
MERNスタックを構築してみたい、という方へ
実際にどんなTutorialがあるか調べてみました。
Learn the MERN Stack - Full Tutorial (MongoDB, Express, React, Node.js)
https://www.youtube.com/watch?v=7CqJlxBYj-M
英語だけど、一番簡単なMERNアプリを作っている気がします。The MERN Stack Tutorial – Building A React CRUD Application From Start To Finish
https://codingthesmartway.com/the-mern-stack-tutorial-building-a-react-crud-application-from-start-to-finish-part-1/
こちらも英語です。youtubeにも上がっているけど、ちょっと動画は・・・って方はこちらがイイかも。MERN Stack Front To Back: Full Stack React, Redux & Node.js
https://www.udemy.com/course/mern-stack-front-to-back/
英語です。有料のUdemyですが、こちらは実際に作ってみました。ReactもHooks使ったりとモダンに扱っていたため、筆者としてはオススメです。まとめ
実際に作成しようとなった場合、ドキュメントが少ない、そもそも日本語で書かれたMERNのチュートリアルが見つからない、と色々と不安な点はあると感じます。しかし、Javascriptのみで書けるという利点は大きいです。
最近のReactJSは、使用傾向が高いということ
Microsoft, Yahooなど、NodeJSの推薦会社が大きいことなどを踏まえると、一度自作のアプリケーションを作ってみてもイイかと思います。
参考にした資料
What is MERN Stack?
https://www.educative.io/edpresso/what-is-mern-stack
Node.jsのMVCフレームワーク「Express」の基礎知識とインストール (1/3)
https://www.atmarkit.co.jp/ait/articles/1503/04/news047.html#011
初心者向け!3分で理解するNode.jsとは何か?
https://eng-entrance.com/what-is-nodejs
- 投稿日:2020-03-14T15:08:54+09:00
Sequelize(PostgreSQL)で月次の集計を行う
例えば、特定の会社に所属するアカウントの新規作成数を月次で集計したい場合(そんな状況があるのかどうかはさておき)
想定結果
month cnt 2020-03 10 PostgreSQL
SELECT TO_CHAR(created_date, 'YYYY-mm') AS month, COUNT(user_id) AS created_cnt FROM users WHERE company_id = 1 GROUP BY monthSequelize
const sequelize = require('sequelize'); const userCtrl = require('../models/userCtrl') ... const res = await userCtrl.findAll({ attributes: [ [sequelize.fn('to_char', sequelize.col('created_date'), 'YYYY-mm'), 'month'], [sequelize.fn('count', sequelize.col('user_id')), 'created_cnt'] ], where: { company_id: 1, }, group: ['month'], });
sequelize.fn
...データベース関数を指定
sequelize.col
...対象のカラムを指定蛇足
MySQLではTO_CHAR関数の代わりに
DATE_FORMAT関数
を使う
指定するフォーマットには、「%」文字をつけるSELECT DATE_FORMAT(created_date, '%Y-%m') AS month, COUNT(user_id) AS created_cnt ...参考
Sequelize公式 - sequelize.fn
MySQL5.6リファレンスマニュアル - DATE_FORMAT
- 投稿日:2020-03-14T13:03:25+09:00
Sessionを改めて勉強する
Sessionを利用するときはライブラリを使ってばかりで、中身をきちんと理解していなかったのでプレーンなNode.js/TypeScriptを使って勉強してみます。
コード
じゃあ早速Node.jsでコードを書いていきます。
import { IncomingMessage, ServerResponse } from 'http'; const http = require('http') const session = new Map<string, Map<string, string>>(); let id = 0; // CookieをMap型に変換する const getCookies = (req: IncomingMessage): Map<string, string> => { if (!req.headers.cookie) return null; let cookieMap = new Map<string, string>(); req.headers.cookie.split(';').forEach(cookie => { const data = cookie.split('='); cookieMap.set(data[0], data[1]); }); return cookieMap; }; const app = function(req: IncomingMessage, res: ServerResponse, next: Function) { const cookies = getCookies(req); let sessionId = (cookies? cookies.get('id') : null); if (sessionId) { const sessionData = session.get(sessionId); console.log('session id:' + id + ', userName:' + sessionData.get('userName')); } else { id++; session.set(String(id), new Map<string, string>().set('userName', 'Taro_' + id)); res.setHeader('Set-Cookie', 'id=' + id + ';'); } res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello World\n'); }; http.createServer(app).listen(3000);はい。これだけです。
試してみます。$ curl -i localhost:3000/ HTTP/1.1 200 OK Set-Cookie: id=1; Content-Type: text/plain Date: Fri, 13 Mar 2020 11:48:51 GMT Connection: keep-alive Transfer-Encoding: chunked Hello World初回接続時には、セッションが作成され、クッキーにセッションidが返却されます。
Set-Cookie: id=1;
の部分です。$ curl -i -H 'Cookie: id=1' localhost:3000/ HTTP/1.1 200 OK Content-Type: text/plain Date: Fri, 13 Mar 2020 11:49:08 GMT Connection: keep-alive Transfer-Encoding: chunked Hello World # サーバの出力値 session id:1, userName:Taro_1次に接続する際には、クッキーにセッションidを渡してあげることで、サーバ側でもセッション内のデータを取得・利用することが可能になります。
というのがコードで表現したセッションです。
解説していきます。解説
Cookieを利用する
HTTPはステートレスです。状態を保持させません。
もし状態を保ちたい時にはCookieを利用します。
Cookieはクライアント側に保持します。Node.jsでのクッキー返却方法// Set-CookieをHeaderに付与することでクッキーを返却可能です res.setHeader('Set-Cookie', 'id=' + id + ';');クライアント側に保持するので改ざん可能です。そのため、改ざんされたくないような重要な情報はセッションに保存する必要があります。
セッションデータの保持
セッションはセッションIDを発行し、クッキーに保有させることでセッション情報を利用可能になります。
今回セッションIDは連番で作成していますが、セッションIDを推測されてしまうと重要な情報が閲覧されてしまう可能性があるため、ハッシュ値などを利用してランダムな値を発行させます。
セッションは以下のような場所に保存します。
- メモリ
- DB
- KVS
- ファイル
今回は以下のようにメモリに保存しています。
メモリにセッションを保持const session = new Map<string, Map<string, string>>(); session.set(String(id), new Map<string, string>().set('userName', 'Taro_' + id));以上。
- 投稿日:2020-03-14T02:52:52+09:00
2020年から始めるAzure Cosmos DB - Node.js で CRUD アプリを作る
この記事について
本記事は、2020年3月6日 (米国時間) にて、Azure Cosmos DB に新しく Free Tier (無償利用枠) が登場したことに伴い、改めて Azure Cosmos DB を色々と触っていく試みの 2 回目です。
今回は、Microsoft Docs のチュートリアルを参考に、Express.js を使って、Azure Cosmos DB に CRUD を行う 簡易な Web アプリケーションの作成および実行を行います。
※ Express.js について知りたい方は、以下の記事を参照してください。対象読者
- Azure Cosmos DB について学習したい方
- Azure Cosmos DB を使ってみたい方
- Node.js で Azure Cosmos DB への CRUD 操作を行いたい方
- 鬼滅の刃が好きな方 (笑)
開発環境準備
環境
OS は好きなものを使ってください。今回、筆者は以下の macOS 環境を使用しています。
- OS: macOS Catalina Version 10.15.3
- Node.js: v12.16.1
Azure Cosmos DB
前回の記事を参考にして、新しく Azure Cosmos DB を作成します。
Visual Studio Code
インストールがまだの方は、リンクより、インストーラーをダウンロードしてください。
※コードエディタはお好きなものを利用頂いて問題ありませんが、本記事では、一部 Visual Studio Code の拡張機能を利用します。
Visual Studio Code を起動後、拡張機能の画面より Azure Cosmos DB の拡張機能をインストールします。
インストールが完了すると、メニューに Azure のアイコンが追加されます。
Azure アイコンを選択すると、[COSMOS DB] タブが表示されるので、[Sign in Azure...] を選択し、Azure にサインインします。サインインに成功すると、前回作成した Azure Cosmos DB アカウント、およびデータベースやコンテナが確認できます。
Node.js
公式サイトより、LTS 版のインストーラーをダウンロードし、インストールを行ってください。
開発
データベースの作成
今回の Web アプリケーション用に、新しくデータベースを作成します。
前回記事 と同様に、Azure にログインし、Azure Cosmos DB アカウントの [データ エクスプローラー] 画面を表示します。
[New Container] 右横からメニューを展開し、[New Database] を選択します。[New Database] 画面が表示されますので、以下の内容を入力し、[OK] を選択してデータベースを作成します。
- Database id: DamonSlayer
- Provision throughput: On
- Throughput: Manual, 400
データベースが正常に作成され、一覧に [DamonSlayer] データベースが表示されたことを確認します。
[DamonSlayer] データベースの右横にある [・・・] を選択し、メニューより [New Container] を選択します。[Add Container] 画面が表示されますので、以下の内容を入力し、[OK] を選択してコンテナーを作成します。
- Database id: Use existing, DamonSlayer
- Container id: Characters
- Indexing: Automatic
- Partition Key: /category
- My partition key is larger than 100 bytes: Off
- Provision dedicated throughput for this container: Off
コンテナーが正常に作成され、一覧に [Characters] コンテナーが表示されたことを確認します。
※Visual Studio Code の拡張機能を利用して、新しくデータベースおよびコンテナーを作成することも可能ですが、Throughput が 1000 からしか選択できず、無償枠の範囲を超過してしまうため、ご注意ください。
CRUD アプリの仕様
今回は
簡易的なもの
のため、指定の URL に GET でアクセスした際に、CRUD 処理を行うこととします。
CRUD 処理にて必要となる情報については、クエリパラメータで送信します。
※本来のアプリケーション開発では、非現実的な仕様のため、そのまま流用することは避けてください。ただし、Express.js を使用したアプリケーション開発の経験がある方であれば、POST 送信や JWT を使った認証など、一部コードを書き換えることで本番に近い利用も可能にできるとは思っています。プロジェクト作成
プロジェクトのルートディレクトリを作成します。
本記事では、azure-cosmosdb-samples
というディレクトリを作成して使用します。mkdir -p azure-cosmosdb-samplesルートディレクトリを作成したら、
npm init
で package.json を作成します。cd azure-cosmosdb-samples npm init -y実行すると、ルートディレクトリ直下に package.json が作成されます。
package.json 内にある main 要素について、index.js から app.js に書き換えます。package.json{ "name": "azure-cosmosdb-samples", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }TypeScript および Express.js のインストール
今回は、Node.js + Express.js + TypeScript で開発を行うため、Express.js と TypeScript をインストールします。
npm install body-parser cookie-parser cors express morgan npm install --save-dev @types/body-parser @types/cookie-parser @types/cors @types/express @types/node @types/morgan npm-run-all ts-node ts-node-dev typescriptインストールが完了したら、TypeScript のバージョンを確認します。
筆者の環境では、「Version 3.8.3」となっています。npx tsc -v
実行結果Version 3.8.3バージョンが正常に確認できたら、tsconfig.json を作成します。
npx tsc --init
コマンドを実行すると、ルートディレクトリ配下に
tsconfig.json
が作成されます。
tsconfig.json の中には様々な要素が記載されていますが、今回は開発に必要となる以下の要素のみ、設定をします。tsconfig.json(一部){ "compilerOptions": { "target": "ES2019", "module": "commonjs", "lib": [ "ES2019", "DOM" ], "sourceMap": true, "outDir": "./dist", "strict": true, "typeRoots": [ "./node_modules/@types" ], "esModuleInterop": true, "forceConsistentCasingInFileNames": true }, "include": [ "src/**/*.ts" ], "exclude": [ "node_modules" ] }tsconfig.json を更新したら、package.json に戻り、scripts 要素を更新します。
package.json(scripts要素部分のみ記載){ "scripts": { "dev": "ts-node-dev --respawn src/app.ts", "clean": "rimraf dist/*", "tsc": "tsc", "build": "npm-run-all clean tsc", "start": "npm run build && node ./dist/app.js" }, }scripts 内にある dev にて、
ts-node-dev
の指定をしているため、ルートディレクトリ以下に .node-dev.json を作成します。.node-dev.json{ "notify": false }@azure/cosmos のインストール
Azure Cosmos DB SQL API 用の JavaScript および Node.js SDK ライブラリをインストールします。
このライブラリを利用する事で、簡単に Azure Cosmos DB へ接続および操作を行うことが可能になります。npm install @azure/cosmos
コーディング
準備ができたので、実際のコーディングを行っていきます。
ルートディレクトリ以下に、新しくsrc
ディレクトリを作成します。
TypeScript のコードは、この src ディレクトリ以下に記述していきます。mkdir -p srcsrc/class
送信されたリクエストに対するレスポンスのデータ型を定義します。
src/class/resJson.tsexport interface ResJson { success: boolean; message: string; data: any; }src/common
(あんまり好きではないですが、よくある共通なんとか〜以外に良いディレクトリを思いつきませんでした。。)
実際にレスポンスを送信するクラスを定義します。src/common/appRes.tsimport { Response, Request, NextFunction } from 'express'; import { ResJson } from '../class/resJson'; export class AppRes { public static sendJson (res: Response, isSuccess: boolean = false, message: string = '' , jsonData: any = null) { const obj: ResJson = { data: jsonData, message: message, success: isSuccess }; res.set('Cache-Control', 'no-cache').json(obj); return; } public static sendError (next: NextFunction, message: string, err?: any): void { let errors: any = []; if (err instanceof Array) { err.forEach((e) => { errors.push(e); }) } else { errors.push(err); } next({ message: message, data: errors }); return; } }src/config
アプリの設定値を定義します。
COSMOSDB_CONFIG
の中にて、Azure Cosmos DB への接続に使用する値を定義します。
endpoint
およびkey
の部分は、Azure ポータル上で確認できる URI および プライマリ キー の値に置き換えてください。src/config/appConfig.tsexport class AppConfig { public static PORT_NUMBER = 3000 public static MAX_REQUEST_SIZE = 20000000 public static COSMOSDB_CONFIG = { endpoint: "<Your Azure Cosmos account URI>", key: "<Your Azure Cosmos account key>", databaseId: "DamonSlayer", containerId: "Characters", partitionKey: { kind: "Hash", paths: ["/category"] } } }src/controllers
コントローラー部分を定義します。コントローラーの中で
@azure/cosmos
を利用した CRUD 処理を実装しています。CRUD の各詳細については、次回の記事で説明しようと思います。src/controllers/cosmosdb.controller.tsimport { CosmosClient, Database, Container } from '@azure/cosmos'; import { NextFunction, Request, Response } from 'express'; import { AppRes } from '../common/appRes'; import { AppConfig } from '../config/appConfig'; export class CosmosDbController { private _errors: any; public async fetchList(req: Request, res: Response, next: NextFunction) { try { const { endpoint, key, databaseId, containerId } = AppConfig.COSMOSDB_CONFIG; const client: CosmosClient = new CosmosClient({ endpoint, key }); const database: Database = client.database(databaseId); const container: Container = database.container(containerId); const querySpec = { query: "SELECT * FROM Items" }; const { resources: items } = await container.items .query(querySpec) .fetchAll(); console.info("fetch success!"); AppRes.sendJson(res, true, "fetch success!", items); } catch (e) { console.error(e.message); this._errors.push(e.message); AppRes.sendError(next, "fetch error.", this._errors); } } public async fetch(req: Request, res: Response, next: NextFunction) { try { const { endpoint, key, databaseId, containerId } = AppConfig.COSMOSDB_CONFIG; const client: CosmosClient = new CosmosClient({ endpoint, key }); const database: Database = client.database(databaseId); const container: Container = database.container(containerId); const querySpec = { query: `SELECT * FROM Items WHERE Items.id = "${req.query.id}"` }; const { resources: items } = await container.items .query(querySpec) .fetchAll(); console.info("fetch success!") if (items.length == 0) { AppRes.sendJson(res, true, "No data.", items); } else { AppRes.sendJson(res, true, "fetch success!", items); } } catch (e) { console.error(e.message); this._errors.push(e.message); AppRes.sendError(next, "fetch error.", this._errors); } } public async create(req: Request, res: Response, next: NextFunction) { try { const { endpoint, key, databaseId, containerId } = AppConfig.COSMOSDB_CONFIG; const client: CosmosClient = new CosmosClient({ endpoint, key }); const database: Database = client.database(databaseId); const container: Container = database.container(containerId); const newItem = { id: req.query.id, category: req.query.category, name: req.query.name, description: "", isAlive: true }; await container.items.create(newItem); AppRes.sendJson(res, true, "create success!", newItem); } catch (e) { console.error(e.message); this._errors.push(e.message); AppRes.sendError(next, "create error.", this._errors); } } public async update(req: Request, res: Response, next: NextFunction) { try { const { endpoint, key, databaseId, containerId } = AppConfig.COSMOSDB_CONFIG; const client: CosmosClient = new CosmosClient({ endpoint, key }); const database: Database = client.database(databaseId); const container: Container = database.container(containerId); const updateItem = { id: req.query.id, category: req.query.category, name: req.query.name }; await container.item(req.query.id, req.query.category) .replace(updateItem); AppRes.sendJson(res, true, "update success!", updateItem); } catch (e) { console.error(e.message); this._errors.push(e.message); AppRes.sendError(next, "update error.", this._errors); } } public async delete(req: Request, res: Response, next: NextFunction) { try { const { endpoint, key, databaseId, containerId } = AppConfig.COSMOSDB_CONFIG; const client: CosmosClient = new CosmosClient({ endpoint, key }); const database: Database = client.database(databaseId); const container: Container = database.container(containerId); await container.item(req.query.id, req.query.category).delete(); AppRes.sendJson(res, true, `delete item id=${req.query.id} category=${req.query.category}`); } catch (e) { console.error(e.message); this._errors.push(e.message); AppRes.sendError(next, "delete error.", this._errors); } } }src/routes
先ほど作成した CosmosDbController クラスに紐づく、ルーティングを行うクラスを定義します。
src/routes/cosmosdbRouter.tsimport { NextFunction, Request, Router, Response } from 'express'; import { CosmosDbController } from '../controllers/cosmosdb.controller'; export class CosmonDbRouter { router: Router; controller: CosmosDbController; constructor () { this.router = Router(); this.controller = new CosmosDbController(); this.init(); } init () { this.router.get('/list', this.controller.fetchList); this.router.get('/detail', this.controller.fetch); this.router.get('/create', this.controller.create); this.router.get('/update', this.controller.update); this.router.get('/delete', this.controller.delete); } } const cosmosdbRouter = new CosmonDbRouter(); cosmosdbRouter.init(); export default cosmosdbRouter.router;src
アプリの起動時に最初に実行される処理を定義します。
この中で、Express の Web サーバの起動なども行います。src/app.tsimport bodyParser from 'body-parser'; import cookieParser from 'cookie-parser'; import express from 'express'; import { NextFunction, Request, Response } from 'express'; import logger from 'morgan'; import cors from 'cors'; import { AppRes } from './common/appRes'; import { AppConfig } from './config/appConfig'; import CosmonDbRouter from './routes/cosmosdbRouter'; class App { public express: express.Express; constructor() { this.express = express(); this.middleware(); this.routes(); } private middleware(): void { this.express.use(cors({ credentials: true, methods: 'GET', origin: [''] })); this.express.use((req: Request, res: Response, next: NextFunction) => { console.debug((new Date().toLocaleDateString()) + '@@@Request Url' + req.url); next(); }) this.express.use(bodyParser.json({ limit: AppConfig.MAX_REQUEST_SIZE })); this.express.use(cookieParser()); this.express.use(logger('dev')); } private routes(): void { this.express.use('/api/cosmosdb', CosmonDbRouter); this.express.use((req: Request, res: Response, next: NextFunction) => { next({ message: `Requested Path is undefined. url=${req.url}` }); }) this.express.use((err: any, req: Request, res: Response, next: NextFunction) => { if (!res.headersSent) { AppRes.sendJson(res, false, err.message, err.data); } }); } } const port = AppConfig.PORT_NUMBER; const app = new App(); app.express.listen(port, () => { console.info(`Waiting at port ${port}. DateTime=${escape(new Date().toLocaleDateString())}`); }).on('error', (error) => { console.error(`Port ${port} does not open. \r\n${error.message}`); process.exit(1); });サンプルデータ登録
CRUD アプリを作成しましたが、今のままでは Azure Cosmos DB には 1 つもデータがありません。
そこで、Azure Cosmos DB にテスト用のサンプルデータを登録していきます。ルートディレクトリ以下に、sample.json ファイルを作成します。
sample.json[ { "id": "1", "category": "main-character", "name": "竈門 炭治郎", "age": 15, "height": 165, "description": "妹を救い、家族の仇討ちを目指す、心優しい少年。鬼や相手の急所などの“匂い”を嗅ぎ分けることができる。", "isAlive": true }, { "id": "2", "category": "main-character", "name": "竈門 禰?豆子", "age": 14, "description": "炭治郎の妹。鬼に襲われ、鬼になってしまうが、他の鬼とは違い、人である炭治郎を守るよう動く。", "isAlive": true }, { "id": "3", "category": "enemy", "name": "鬼舞辻 無惨", "description": "禰?豆子を鬼に変えた者で炭治郎の宿敵。普段は人間のふりをして暮らしている。", "isAlive": true }, { "id": "4", "category": "friend", "name": "煉獄 杏寿郎", "age": 20, "description": "鬼殺隊の“柱”の一人。“炎の呼吸”で鬼を殲滅する。", "isAlive": false } ]冒頭にインストールした Visual Studio Code の拡張機能 [Azure Cosmos DB]では、
json ファイルを使ってデータをインポート
させることができます。[DamonSlayer] -> [Characters] を右クリック -> [Import Document into a Collection...] を選択し、sample.json 選択してデータをインポートします。
実行
ルートディレクトリに移動し、
npm start
で作成した CRUD アプリを起動します。cd azure-cosmosdb-sample npm start
コマンドを実行することで、
dist
ディレクトリが新しく作成され、TypeScript から JavaScript にコンパイルされたソースコードが出力されます。CRUD アプリはこの出力された JavaScript を使って動いています。
以下のような実行結果が出力されれば、正常に起動ができています。実行結果(例)Waiting at port 3000. DateTime=2020-3-14一覧データ取得
Webブラウザを起動し、以下の URL にアクセスします。
http://localhost:3000/api/cosmosdb/list先ほど登録したデータの一覧が取得され、画面に表示されます。
ID に紐づくデータの取得
指定した id に一致するデータのみ取得する場合は、以下の URL にアクセスします。
URL のクエリパラメータ(? マーク以降の文字列)内で、任意のid値を入力して下さい。
(今回は、id が "3" である 鬼舞辻 無惨 のデータを取得します。)http://localhost:3000/api/cosmosdb/detail?id=3データの登録
新しくデータを登録する場合は、以下の URL にアクセスします。
クエリパラメータ内にて指定した id、category、name の値を使ってデータを登録することができます。
(今回は、id を "5" として 鱗滝 左近次 のデータを登録します。)http://localhost:3000/api/cosmosdb/create?id=5&category=friend&name=鱗滝%20左近次 ※URL エンコード版 http://localhost:3000/api/cosmosdb/create?id=5&category=friend&name=%E9%B1%97%E6%BB%9D%20%E5%B7%A6%E8%BF%91%E6%AC%A1データの更新
既存のデータを更新する場合は、以下の URL にアクセスします。
クエリパラメータ内にて指定した id と category に紐づくデータの name 値を、同じくクエリパラメータ内にて指定した name の値に書き換えます。
(今回は、id を "5" として name 値を 鱗滝 左近次 から 冨岡 義勇 に更新します。)http://localhost:3000/api/cosmosdb/update?id=5&category=friend&name=冨岡%20義勇 ※URL エンコード版 http://localhost:3000/api/cosmosdb/update?id=5&category=friend&name=%E5%86%A8%E5%B2%A1%20%E7%BE%A9%E5%8B%87データの削除
既存のデータを削除する場合は、以下の URL にアクセスします。
クエリパラメータ内にて指定した id と category に紐づくデータを削除します。
(今回は、id を "5" 、 category が "friend" のデータ 冨岡 義勇 を削除します。)http://localhost:3000/api/cosmosdb/delete?id=5&category=friendさいごに
今回は、Node.js + Express.js + TypeScript を使って、Azure Cosmos DB への簡易的な CRUD アプリを作成しました。
しかしながら、このアプリは全てのリクエストが GET
で行われており、実際の本番環境には使えるものではありません。
ただし、この CRUD アプリに多少手を加えることで、簡単に POST で同じ通信を行ったり、認証された状態でしか CRUD を実行できないように、動作を変更させることは可能になります。実際に、これを読んだあなたの手で、その処理を実装してみてください。
また今回のソースコードの中には、一部無駄なコードの書き方をしている部分があります。もっと簡略化できるポイントがないか、探してみてください。そして、見つけたら直してみてください。今回のソースコードは GitHub にて公開しています。是非 Pull Request してみてください。
関連リンク
前回記事
GitHub
その他
参考情報
Microsoft Docs
npm
Hatena Blog