JavaScriptだけでWebサイト開発

node.js + Express + mongodb系 + React でサービスを作るメモ

node.js+React CMS開発-モデル定義

CMS開発シリーズの続きです

今回は前回作成した雛形にmongooseスキーマ&モデルの定義を実装します。

目次

mongooseのインストール

$ cd ~/nexpress
$ npm install --save mongoose

auto increment を行うmongoose-sequenceを導入

MySQLなどのRDBで使われる自動採番(sequence) を利用したいのでmongoose-sequenceをインストール

$ npm install --save mongoose-sequence

ユーザーパスワードの暗号化のためmongoose-bycryptを導入

パスワードを暗号化して保存するためフィールドの暗号化と照合ができるプラグインmongoose-bycryptをインストール

$ npm install --save mongoose-bycrypt

モデル定義をするディレクトリ構造を決める

nexpress
├── README.md
├── app.js
├── bin
├── config.js     <----- アプリケーション共通の設定情報
├── db.js         <----- mongodb接続や,mongoose,puluginに関する共通設定
├── models/       <----- ここにモデルごとにファイルで配置する
├── node_modules/
├── package-lock.json
├── package.json
├── public/       <----- 静的ファイル
├── routes/       <----- ルーティング
└── views/        <----- ビュー

共通module

config.js

アプリケーション全体を通して使用するパラメータなどを定義します。

// config.js
const config = {
 app: {
   port: 3000
 },
 db: {
   host: 'localhost',
   port: 27017,
   name: 'nexpress'
 },
 secret: {
   key:  '#%$SomethingRandomString&%$'
 }
};

module.exports = config;

db.js

  • データベースへの接続
  • mongoose プラグインの追加
var config = require('./config');
var mongoose = require('mongoose');  // mongoose 利用
const AutoIncrement = require('mongoose-sequence')(mongoose); // 自動採番プラグイン

const { db: { host, port, name } } = config;

const option = {
  useMongoClient: true,
  poolSize: 10
};
mongoose.Promise = global.Promise;
mongoose.connect(`mongodb:\/\/${host}:${port}/${name}`, option); // 接続
mongoose.AutoIncrement = AutoIncrement; 

module.exports = mongoose;

モデル定義

node.js+React CMS を設計する(データベース仕様))で定義したスキーマをnexpress/modelsディレクトリに定義する

user.js

ユーザー情報

var mongoose      = require('../db'); // 接続とsequenceの初期化が行われている
var Schema        = mongoose.Schema;

// 定義
var userSchema = new Schema ({
  user_id   : Number,
  login     : String,
  password  : String
});

// user_idは自動採番
userSchema.plugin(mongoose.AutoIncrement, { inc_field: 'user_id'});
// passwordフィールドを自動暗号化
userSchema.plugin(require('mongoose-bcrypt'),{ fields: ['password'] });

module.exports = mongoose.model('User', userSchema);

site.js

サイト情報

var mongoose      = require('../db');
var Schema        = mongoose.Schema;

var siteSchema = new Schema ({
  site_id: Number,
  name   : String,
  title  : String
});

siteSchema.plugin(mongoose.AutoIncrement, { inc_field: 'site_id' });

module.exports = mongoose.model('Site', siteSchema);

user-site.js

サイトの所有者、利用者、共同編集者ユーザーの登録情報。 ユーザーとサイトのリレーション

var mongoose      = require('../db');
var Schema        = mongoose.Schema

var userSiteSchema = new Schema ({
  user_id   : { type: Number, refs: 'User' },
  site_id   : { type: Number, refs: 'Site' },
  role      : String
});

module.exports = mongoose.model('UserSite', userSiteSchema);

category.js

カテゴリ情報

var mongoose      = require('../db');
var Schema        = mongoose.Schema;

var categorySchema = new Schema ({
  site_id: { type: Number, refs: Site },
  category_id: Number
  name   : String,
  title  : String
});

categorySchema.plugin(mongoose.AutoIncrement, { inc_field: 'category_id'});

module.exports = mongoose.model('Category', categorySchema);

category-category.js

カテゴリ同士の親子関係 カテゴリ間リレーション定義

var mongoose      = require('../db');
var Schema        = mongoose.Schema

var contentCategorySchema = new Schema ({
  category_id  : { type: Number, refs: 'Category' },
  content_id   : { type: Number, refs: 'Content' }
});

module.exports = mongoose.model('ContentCategory', contentCategorySchema);

content.js

コンテンツ、記事情報

var mongoose      = require('../db');
var Schema        = mongoose.Schema;

var contentSchema = new Schema ({
  site_id: { type: Number, refs: Site },
  content_id: Number,
  user_id: { type: Number, refs: User},
  title   : String,
  summary  : String,
  image: String,
  publish_date: { type: Date, default: Date.now },
  expire_date: { type: Date, default: null },
  article: [Schema.Types.Mixed]
});

contentSchema.plugin(mongoose.AutoIncrement, { inc_field: 'content_id'});

module.exports = mongoose.model('Content', contentSchema);

content-category.js

コンテンツとカテゴリのリレーション

var mongoose      = require('../db');
var Schema        = mongoose.Schema

var contentCategorySchema = new Schema ({
  category_id  : { type: Number, refs: 'Category' },
  content_id   : { type: Number, refs: 'Content' }
});

module.exports = mongoose.model('ContentCategory', contentCategorySchema);

tag.js

タグ情報

var mongoose      = require('../db');
var Schema        = mongoose.Schema;

var tagSchema = new Schema ({
    site_id : { type: Number, refs: Site },
    tag_id  : Number,
    name    : String
});

tagSchema.plugin(mongoose.AutoIncrement, { inc_field: 'tag_id'});

module.exports = mongoose.model('Tag', tagSchema);

content-tag.js

var mongoose      = require('../db');
var Schema        = mongoose.Schema

var contentTagSchema = new Schema ({
  tag_id      : { type: Number, refs: 'Tag' },
  content_id  : { type: Number, refs: 'Content' }
});

module.exports = mongoose.model('ContenTag', contentTagSchema);

file.js

添付画像やアップロードされたファイルの情報

var mongoose      = require('../db');
var Schema        = mongoose.Schema;

var fileSchema = new Schema ({
  site_id: { type: Number, refs: Site },
  file_id: Number,
  user_id: { type: Number, refs: User},
  path   : String
});

fileSchema.plugin(mongoose.AutoIncrement, { inc_field: 'file_id' });

module.exports = mongoose.model('file', fileSchema);

まとめ

  • アプリケーション全体で共有する設定情報を config.js に定義
  • データベース接続およびmongoose共通環境を db.js に定義
  • モデル models/*.jsにモデルごとに定義
  • 各モデルはコントローラで使用するモデルの必要な分だけrequireする
  • データベース接続はpoolして使いまわす
  • アプリケーションでは自動採番フィールド(*_id)をキーにしてリレーションする
  • user.passwordは暗号化する
  • Index,Validationは別途行う

これで基本的なモデルの定義ができました。

:
├── models
│   ├── category-category.js
│   ├── category.js
│   ├── content-category.js
│   ├── content-tag.js
│   ├── content.js
│   ├── file.js
│   ├── site.js
│   ├── tag.js
│   ├── user-site.js
│   └── user.js
:

つづく

©ichi-bit