Quantcast
Channel: Node.jsタグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 8691

新人に負けない本棚管理サイト その4(データベース検索編①)

$
0
0

目次

新人に負けない本棚管理サイト その1(プロローグ)
新人に負けない本棚管理サイト その2(環境構築編)
新人に負けない本棚管理サイト その3(トップページ作成編)
新人に負けない本棚管理サイト その4(データベース検索編①)

目標

  • データベースに問い合わせしてデータを取得する
  • 取得したデータを画面に表示する ←今回はここまで
  • 検索できるようにする

データの準備

使用するデータベースはMariaDBです。
セットアップ方法はその2を参照してください。

テーブル作成

CREATE_TABLE_Books.sql
CREATETABLEBooks(titleVARCHAR(100)primarykey,authorVARCHAR(20),publisherVARCHAR(20),finished__atDATEDEFAULTCURDATE())

仮データ登録

CREATE_TABLE_Books.sql
INSERTINTOBooksVALUES('Python Django超入門','掌田津耶乃','秀和システム','2019/08/31'),('React.js&Next.js超入門','掌田津耶乃','秀和システム',NULL),('PostgreSQL徹底入門 第4版','近藤雄太 他','翔泳社',NULL),('PHPフレームワークLaravel入門 第2版','掌田津耶乃','秀和システム','2019/10/31'),('PostgreSQLから始めるデータベース生活','まぐろ','まぐろのみぞおち','2019/11/03')

一緒にSearchResultComponentで仮に入れていた本データを削除します。

importReactfrom'react';import{Container,Row,Col,Table}from'react-bootstrap';exportdefaultclassSearchResultextendsReact.Component{render(){return(<Container><Row><Tablestripedborderedsize="sm"><thead><tr><th>タイトル</th><th>著者名</th><th>出版社</th><th>読了日</th></tr></thead><tbody>{/* 削除
              <tr>
                <td>Python Django超入門</td>
                <td>掌田津耶乃</td>
                <td>秀和システム</td>
                <td>2019/08/31</td>
              </tr>
             ...
              <tr>
                <td>PostgreSQLから始めるデータベース生活</td>
                <td>まぐろ</td>
                <td>まぐろのみぞおち</td>
                <td>2019/11/03</td>
              </tr>
*/}</tbody></Table></Row></Container>);}}

スタートアッププログラムを変更

Expressのインストール

リクエストの処理を定義するために、Node.jsのフレームワークのExpressをインストールします。

terminal
npm install express

スタートアッププログラム作成

まずプロジェクト直下にserver.jsを作ります。
引用:

server.js
constexpress=require('express')constnext=require('next')constdev=process.env.NODE_ENV!=='production'constapp=next({dev})consthandle=app.getRequestHandler()app.prepare().then(()=>{constserver=express();server.get('*',(req,res)=>{returnhandle(req,res);})server.listen(3000,(err)=>{if(err){throwerr}console.log('> Ready on http://localhost:3000')})}).catch((ex)=>{console.error(ex.stack)process.exit(1)})

次にpackage.jsonのscript部を書き換えます。

"scripts":{"dev":"node server.js","build":"next build","start":"NODE_ENV=production node server.js"}

そして再度npm run devすると、ターミナルに> Ready on http://localhost:3000が表示されると思います。
この段階で(開発用の)Webサーバーが立ち上がったということになります。

404を解決する

今のままでは、/bookmanagerにアクセスしたあとリロードすると404が表示されます。
これはserver.jsで/bookmanagerにアクセスしたときの処理内容を定義していないため、どのページを表示させるか分からなかったためです。

じゃあ定義しよう!!

server.jsに以下のように追記します。

server.js
// (略)app.prepare().then(()=>{constserver=express();// 追記ここからserver.get('/bookmanager',(req,res)=>{returnapp.render(req,res,'/bookmanager',req.query);});// 追記ここまでserver.get('*',(req,res)=>{returnhandle(req,res);})server.listen(3000,(err)=>{if(err){throwerr}console.log('> Ready on http://localhost:3000')})}).catch((ex)=>{console.error(ex.stack)process.exit(1)})

これにより、/bookmanagerにgetリクエストが来たらpages/bookmanager/index.jsを表示させるという定義ができました。
何度リロードしても404になりません!!

データベースへ問い合わせ

最初にページを開いたときに、データベースから本情報を全件取ってきて表示させます。
メインの内容です!!

MariaDBへ接続するためのモジュールを追加

terminal
npm install mariadb

データベース接続情報を定義する

プロジェクト直下にmariadbConnection.jsを作ります。

mariadbConnection.js
constmariadb=require('mariadb/callback');constdbConfig={host:'192.168.xxx.xxx',user:'username',password:'yourpassword',database:'database-name'};constconnection=mariadb.createConnection(dbConfig);module.exports=connection;

データベースからデータ取得

bookmanagerページを開いたときにコンソールにデータを表示させてみましょう。
server.jsを書き換えます。

server.js
// (略)app.prepare().then(()=>{constserver=express();// 変更ここからconstconnection=require('./mariadbConnection');server.get('/bookmanager',(req,res)=>{letquery="SELECT title, author, publisher, DATE_FORMAT(finished_at, '%Y/%m/%d') AS finished_at FROM Books ORDER BY title";connection.query(query,(err,rows)=>{if(err)throwerr;console.log(rows);});returnapp.render(req,res,'/bookmanager',req.query);});// 変更ここまでserver.get('*',(req,res)=>{returnhandle(req,res);})server.listen(3000,(err)=>{if(err){throwerr}console.log('> Ready on http://localhost:3000')})}).catch((ex)=>{console.error(ex.stack)process.exit(1)})

npm run devしてWebサーバーを再起動します。
その後bookmanagerページを開き、ターミナルを見てみると...

コメント 2020-05-28 011021.png

いいっすねぇ~(・∀・)

取得結果を画面にバインド(やることが多いです)

通常のWebアプリでは、以下のように検索する仕組みを作ると思います。

  • 検索ボタンを押したとき、入力値をサーバーへ送る
  • サーバーサイドのプログラムからデータベースへ、検索クエリを投げる
  • 結果を画面へ返す
  • 画面でイイカンジに表示する

つまり検索するたびにサーバーへリクエストが飛ぶため、ヒット件数が多かったりストアドプロシージャ/ファンクションを介したりする場合はそれなりに時間がかかります。
せっかくNextというエクストリームニュージェネレーションフレームワーク(言いたいだけ)を使っているのに、こんなクラシックなやり方で応答時間を増やすのはダメです!

そこで、
最初にbookmanagerページを開いたときに一度だけ全件取得して、検索するときはそのデータから絞り込む
ということをしてみます。
これならデータベースへの問い合わせは初めてページを開くときの一度のみになるので、圧倒的にレスポンスが短くなります。(ページをリロードしたときも初めて開いたとする)

ページオープン時に全件取得

NextにはgetInitialPropsという便利な関数があります。
カンタンに言うと「ページが表示されたとき一度だけ実行される非同期関数」って感じです。
やりたいことにもってこいの関数ですね。
この中でデータベースへ問い合わせをします。

まずbookmanagerページにgetInitialProps関数を追加します。

pages/bookmanager/index.js
importLayoutfrom'../../components/layout';importReactfrom'react';import{Container,Row,Col,Table,Form}from'react-bootstrap';exportdefaultclassIndexextendsReact.Component{// 追記ここからstaticasyncgetInitialProps(){constres=awaitfetch('http://192.168.130.69:3000/bookmanager/get');constallBooks=awaitres.json();return{allBooks};}// 追記ここまでrender(){{/* 略 */}}

getInitialPropsの中でAPIを呼び結果を取得しています。
この呼び出しの定義をserver.jsで記述します。

server.js
app.prepare().then(()=>{constconnection=require('./mariadbConnection');// データベース呼び出し処理は削除してください。server.get('/bookmanager',(req,res)=>{/*
    let query = "SELECT title, author, publisher, DATE_FORMAT(finished_at, '%Y/%m/%d') AS finished_at FROM Books ORDER BY title";
    connection.query(query, (err, rows) => {
      if(err) throw err;
      console.log(rows);
    });
    */returnapp.render(req,res,'/bookmanager',req.query);});// 追記ここからserver.get('/bookmanager/get',async(req,res)=>{letquery="SELECT title, author, publisher, DATE_FORMAT(finished_at, '%Y/%m/%d') AS finished_at FROM Books ORDER BY title";connection.query(query,(err,rows)=>{if(err)throwerr;res.json(rows);// レスポンスに取得データを持たせる});});// 追記ここまでserver.get('*',(req,res)=>{returnhandle(req,res);});server.listen(3000,(err)=>{if(err){throwerr;}console.log('> Ready on http://localhost:3000');});}).catch((ex)=>{console.error(ex.stack);process.exit(1);});

毎度のことながら、npm run devしてアクセスします。
データベースには以下のデータが入っています。

titleauthorpublisherfinisher_at
PHPフレームワークLaravel入門 第2版掌田津耶乃秀和システム2019/10/31
PostgreSQLから始めるデータベース生活まぐろまぐろのみぞおち2019/11/03
PostgreSQL徹底入門 第4版近藤雄太 他翔泳社NULL
Python Django超入門掌田津耶乃秀和システム2019/08/31
React.js&Next.js超入門掌田津耶乃秀和システムNULL
プリンをもっと見守る技術 M5StickVで体験するAIの世界aNo研aNo研2020/05/26

アクセスすると...

コメント 2020-05-28 013937.png

ちゃんと表示されました(;^ω^)

お疲れ様でした

盛りだくさんで書くのも大変でした。
日本語を書くのがへたっぴなので、分かりづらいところがあると思います。
小さい目標を1つずつ達成して、
「現段階で何ができているのか」「次に何ができてほしいか」「ゴールまで到達するにはあと何ができなければならないか」
をまとめるようにすると、ワカラナイパニックに陥ることは少ないと思います。

と、私の会社の先輩が言っていました。

次回

条件を入力して検索できるようにします。


Viewing all articles
Browse latest Browse all 8691

Trending Articles