Express/Node.jsとMongoDBで制作~付箋アプリ~

はじめに

↑の画像みたいに適当な名前をつけて付箋を残すWebアプリを作ってみたいと思います。本当はVue.jsを使ってお洒落なSPAを作ってみたかったのですが、バックエンドのExpressからフロントエンドのVue.jsに値を渡す方法が見つからなかったので断念しました。

  • CentOS7
  • Express/Node.js
  • MongoDB

準備

最新版のNode.jsをインストールするDockerfileがありましたので、これを利用します。Dockerが無い人も読み替えて17行以降実施すれば問題無い筈です。

# cat Dockerfile 
FROM centos:7

# update
RUN yum -y update && yum clean all

# set locale
RUN yum reinstall -y glibc-common && yum clean all
RUN localedef -f UTF-8 -i ja_JP ja_JP.UTF-8
ENV LANG ja_JP.UTF-8
ENV LANGUAGE ja_JP:ja
ENV LC_ALL ja_JP.UTF-8
RUN unlink /etc/localtime
RUN ln -s /usr/share/zoneinfo/Japan /etc/localtime

# nodejs install
RUN curl -sL https://rpm.nodesource.com/setup_13.x | bash
RUN yum -y install nodejs
WORKDIR /myapp
 イメージ作成
# docker build -t centos:7 .
コンテナ作成
# docker run -itd --name stcnote -p 27017:27017 -p 3000:3000 centos:7 /sbin/init
# docker exec -it stcnote /bin/bash
  • -p 27017:27017
    • MongoDB用ポート
  • -p 3000:3000
    • Node.js用ポート
  • /sbin/init
    • systemctlコマンド実行するため

MongoDB設定

リポジトリを追加。未だにEOFをダブルクォーテーションで囲むと変数が展開されない理由が理解出来ていないのをどうにかしたいです。

# cat <<"EOF" > /etc/yum.repos.d/mongodb-org-4.0.repo
[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc
EOF
# yum install -y mongodb-org
# systemctl start mongod

インストールと起動まで確認出来たらユーザを作成します。

# mongo
admin データベースに接続
> use admin
管理ユーザ登録
> db.createUser({user:"admin", pwd:"password", roles:[{role:"root", db:"admin"}]})
ユーザ確認
> db.getUsers()
一旦抜ける
> exit

/etc/mongod.confを見ていきます。標準の設定ファイルには

storage:
  dbPath: /var/lib/mongo

となっているのですが、/data/dbにデータが格納される仕様になっているみたいなので下記コマンドを実行します。設定ファイルの方は直さなくて良いです。

# mkdir -p /data/db && chown -R mongod:mongod /data/db

また認証機能を使用するので下記を追記します。

security:
  authorization: enabled

AWSなどでグローバルIPを使っている人はバインドIPを設定する。

# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0  # Enter 0.0.0.0,:: to bind to all IPv4 and IPv6 addresses or, alternatively, use the net.bindIpAll setting.

再起動後接続確認をします。

# systemctl restart mongod
# mongo -u admin -ppassword -authenticationDatabase admin
>

開発用にダミーのドキュメントを作成します。

database 一覧表示
> show dbs
database 選択
> use admin
使用中database 確認
> db
admin
コレクション作成
> db.createCollection('links');
> show collections
サンプルデータ挿入
> db.links.insert({ linkname : "夜マオふにゃふにゃ", linkurl : "https://youtu.be/6cbqUl-3xDQ?t=65" });

Express設定

雛形作成とモジュール追加します。npm initは全部Enterで良いです。

# npm init
# npm install express --save
# npm install mongodb --save
# npm install ejs --save

ルートファイル作成。

# vi index.js
const express = require('express')
const bodyParser = require('body-parser')

// mongodb読み込み
const mongodb = require('mongodb')
const ObjectId = require('mongodb').ObjectID;
const MongoClient = mongodb.MongoClient

const app = express()
app.use(bodyParser.json())
app.set("view engine", "ejs");

app.get('/', function(req, res) {
  MongoClient.connect('mongodb://admin:password@【WebSV IP】:27017', (err, client) => {
    if (!err) {
      const db = client.db("admin");
      var collection = db.collection("links");
      collection.find().toArray((error, documents) => {
        var data = documents;
        res.render("index.ejs", {data:data});
      });
    } else {
      console.log(err);
    }
  });
})

app.use(bodyParser.urlencoded({
  extended: true
}));


app.post('/', function(req, res) {
  // 挿入時
  console.log(req.body);
  if (req.body.LINK ) {
    MongoClient.connect('mongodb://admin:password@【WebSV IP】:27017', (err, client) => {
      if (!err) {
        const db = client.db("admin");
        var collection = db.collection("links");
        collection.insertOne({
          "linkname": req.body.TEXT,
          "linkurl": req.body.LINK
        }, (error, result) => {
          console.log(error);
        });
        req.body.TEXT = null;
        req.body.LINK = null;
        collection.find().toArray((error, documents) => {
          var data = documents;
          res.render("index.ejs", {data:data});
        });
      } else {
        console.log(err);
      }
    });
  }
  // 削除時
  if (req.body.delete) {
    var docid = req.body.delete;
    MongoClient.connect('mongodb://admin:password@【WebSV IP】:27017', (err, client) => {
      if (!err) {
        const db = client.db("admin");
        var collection = db.collection("links");
        collection.deleteMany(
          { _id: { $eq: ObjectId(docid) } },
          (error, result) => {
            console.log(error);
          }
        );
        collection.find().toArray((error, documents) => {
          var data = documents;
          res.render("index.ejs", {data:data});
        });
      } else {
        console.log(err);
      }
    });
  }
})

app.listen(process.env.PORT || 3000)
  • body-parser, urlencode
    • JSON形式のPOSTリクエストをreq.bodyにセットする
    • これしないとPOSTリクエストを扱えない。地味にハマった。

ejsファイル作成。

# mkdir views
# vi views/index.ejs
# vi views/links.ejs
# vi views/form.ejs
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <link rel="stylesheet" href="/public/bootstrap/css/bootstrap.min.css" />
    </head>
    <body>
        <div class="container">
            <h1>StickeyNote By Express/MongoDB</h1>
            <%- include("form.ejs") %>
            <%- include("links.ejs", data) %>
        </div>
    </body>
</html>
<table border="1">
<tr>
<th>TEXT</th><th>LINK</th><th>DELETE</th>
</tr>
<% for (let item of data) { %>
    <tr>
    <td><%- item.linkname %></td><td><a href="<%= item.linkurl %>" target="_blank"><%= item.linkurl %></a></td><td><form method="post"><button type="submit" value="<%= item._id %>" name="delete">削除</button></form></td>
    </tr>
<% } %>
</table>
<div>
<form method="post">
  <div>
    <label for="TEXT">TEXT:</label>
    <input type="text" id="TEXT" name="TEXT">
  </div>
  <div>
    <label for="LINK">LINK:</label>
    <input type="text" id="LINK" name="LINK">
  </div>
  <div>
    <input type="submit" value="PUSH">
  </div>
</form>
</div>

自分の場合URLを付箋する事を想定していたのでlinks.esjに自動で<a></a>で囲んでいるのですが、各々で設定を変えてください。条件分岐も可能です。最後にnode index.jsで起動したら完了です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA