4.2 數據庫表/Sequelize Mysql-博客後端Api-NodeJs+Express+Mysql實戰

功能梳理完了之後,我們就能夠開始數據庫表設計了:

數據庫表圖:html

clipboard.png

首先打開Navicat Premium 建立數據庫 blognode

配置以下:mysql

clipboard.png

課前學習:
一、Sequelize 中文API文檔【強烈推薦】 https://itbilu.com/nodejs/npm...
二、Sequelize 和 MySQL 對照
https://segmentfault.com/a/11...
三、使用Sequelize
http://www.liaoxuefeng.com/wi...
四、Sequelize API
https://sequelize.readthedocs...
五、關於「時間」的一次探索
https://segmentfault.com/a/11...

在blogNodejs/models 下web

首先新建 mysql.js 進行mysql鏈接配置(基於Sequelize)sql

var config = require('config-lite');//引入靈活配置文件
var Sequelize = require('sequelize');.//引入Sequelize

var Mysql = new Sequelize(config.mysql.database, config.mysql.user, config.mysql.password, {
    host: config.mysql.host, //數據庫服務器ip
    dialect: 'mysql', //數據庫使用mysql
    port: 3306, //數據庫服務器端口
    pool: {
        max: 5,
        min: 0,
        idle: 10000
    },
});

module.exports = Mysql;

而後根據數據庫圖,依次建立對應的Model數據庫

clipboard.png

這裏以user.js爲示例 單獨說下:express

/**
 * User 用戶表
 */
var Sequelize = require('sequelize');//引入sequelize
var Mysql = require('./mysql');//引入mysql實例化

//定義User用戶表
var User = Mysql.define('user', {
    uuid: {//使用uuid 而不使用
        type: Sequelize.UUID,//設置類型
        allowNull: false,//是否容許爲空
        primaryKey: true,//主鍵
        defaultValue: Sequelize.UUIDV1,//默認值
    }, //uuid
    email: { //郵箱
        type: Sequelize.STRING,
        allowNull: false,
        unique: true, //惟一
        validate: {//設置驗證條件
            isEmail: true,// 檢測郵箱格式 (foo@bar.com)
        },
    },
    password: { //密碼
        type: Sequelize.STRING,
        allowNull: false,
    },
    state: { //狀態 0未激活郵箱、1已激活郵箱
        type: Sequelize.STRING(2),//限制字符個數
        defaultValue: "0", //默認值
    },
}, {
    freezeTableName: true, //開啓自定義表名
    tableName: 'User',//表名字
    timestamps: true, // 添加時間戳屬性 (updatedAt, createdAt)
    createdAt: 'createDate',// 將createdAt字段改個名
    updatedAt: 'updateDate',// 將updatedAt字段改個名
    indexes: [{ // 索引
        type: 'UNIQUE', //UNIQUE、 FULLTEXT 或 SPATIAL之一
        method: 'BTREE', //BTREE 或 HASH
        unique: true, //惟一 //設置索引是否惟一,設置後會自動觸發UNIQUE設置//true:索引列的全部值都只能出現一次,即必須惟一
        fields: ['uuid'], //創建索引的字段數組。每一個字段能夠是一個字段名,sequelize 對象 (如 sequelize.fn),或一個包含:attribute (字段名)、length (建立前綴字符數)、order (列排序方向)、collate (較驗的字段集合 (排序))
    }],
    comment:"User Table",//數據庫表描述
});

module.exports = User;//導出

表都寫完後,新建index.jsnpm

**
 * 數據庫表關係創建
 */
var Mysql = require('./mysql');

//表
var AdminUser = require('./adminUser');//管理員表
var User = require('./user');//用戶表
var UserInfo = require('./userInfo');//用戶信息表
var Article = require('./article');//文章表
var Category = require('./category');//文章類別表
var Attachment = require('./attachment');//文章附件表

/**
 * 關係創建
 */

//用戶-用戶資料
User.hasOne(UserInfo); //1:1

//用戶-文章
User.hasMany(Article); //1:N
Article.belongsTo(User); //1:1

//文章-分類 (定義中間表ArticleCategory 實現多對多)
Article.belongsToMany(Category,{through: 'ArticleCategory'}); //N:N
Category.belongsToMany(Article,{through: 'ArticleCategory'}); //N:N


//基於sequelize自動建立表//【!!注意 首次執行完請註釋掉該段代碼 !!】
Mysql.sync({
    force: true,//是否清空數據庫表
}).then(function() {
    console.log('ok');
});

module.exports = {
    AdminUser: AdminUser,
    User: User,
    UserInfo: UserInfo,
    Article: Article,
    Category: Category,
    Attachment: Attachment,
};

好。到這裏,我們我們打開json

blogNodejs/app.js 寫入如下代碼segmentfault

/**
 * 主入口啓動文件
 * add by wwj
 * 2017-08-24 15:01:48
 */
var express = require('express'); //web 框架
var logger = require('morgan'); //開發模式下log
var bodyParser = require('body-parser'); //json
var path = require('path'); //路徑
var config = require('config-lite'); //讀取配置文件
var winston = require('winston'); //日誌
var expressWinston = require('express-winston'); //基於 winston 的用於 express 的日誌中間件
var models = require('./models'); //臨時添加 爲了生成數據庫表,後面寫到Controllers裏面

//實例化express
var app = express();

// 設置模板目錄
app.set('views', path.join(__dirname, 'views'));
// 設置模板引擎爲 ejs
app.set('view engine', 'ejs');

// log
app.use(logger('dev'));

//設置json
//格式化JSON的輸出
app.set('json spaces', 2);
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
  extended: false
}));
// parse application/json
app.use(bodyParser.json());

// 設置靜態文件目錄
app.use(express.static(path.join(__dirname, 'public'))); //注意:中間件的加載順序很重要。如上面設置靜態文件目錄的中間件應該放到 routes(app) 以前加載,這樣靜態文件的請求就不會落到業務邏輯的路由裏;

//錯誤請求的日誌
app.use(expressWinston.errorLogger({
  transports: [
    new winston.transports.Console({
      json: true,
      colorize: true
    }),
    new winston.transports.File({
      filename: 'logs/error.log'
    })
  ]
}));

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

//app
module.exports = app;

執行一下

npm run dev

clipboard.png

而後去mysql 下看看是否建立成功了(右擊「表」-刷新)

clipboard.png

到這裏,我們的數據庫已經ok啦

下面學習瞭解些業務邏輯寫法

// 字段類型
// STRING
// CHAR
// TEXT
// INTEGER :A 32 bit integer.
// BIGINT :A 64 bit integer.
// FLOAT
// REAL
// DOUBLE
// DECIMAL
// BOOLEAN
// TIME
// DATE
// BLOB

//where
$and: {a: 5}           // AND (a = 5)
$or: [{a: 5}, {a: 6}]  // (a = 5 OR a = 6)
$gt: 6,                // > 6
$gte: 6,               // >= 6
$lt: 10,               // < 10
$lte: 10,              // <= 10
$ne: 20,               // != 20
$not: true,            // IS NOT TRUE
$between: [6, 10],     // BETWEEN 6 AND 10
$notBetween: [11, 15], // NOT BETWEEN 11 AND 15
$in: [1, 2],           // IN [1, 2]
$notIn: [1, 2],        // NOT IN [1, 2]
$like: '%hat',         // LIKE '%hat'
$notLike: '%hat'       // NOT LIKE '%hat'
$iLike: '%hat'         // ILIKE '%hat' (case insensitive) (PG only)
$notILike: '%hat'      // NOT ILIKE '%hat'  (PG only)
$like: { $any: ['cat', 'hat']}
                       // LIKE ANY ARRAY['cat', 'hat'] - also works for iLike and notLike
$overlap: [1, 2]       // && [1, 2] (PG array overlap operator)
$contains: [1, 2]      // @> [1, 2] (PG array contains operator)
$contained: [1, 2]     // <@ [1, 2] (PG array contained by operator)
$any: [2,3]            // ANY ARRAY[2, 3]::INTEGER (PG only)

$col: 'user.organization_id' // = "user"."organization_id", with dialect specific column identifiers, PG in this example

{
  rank: {
    $or: {
      $lt: 1000,
      $eq: null
    }
  }
}
// rank < 1000 OR rank IS NULL

{
  createdAt: {
    $lt: new Date(),
    $gt: new Date(new Date() - 24 * 60 * 60 * 1000)
  }
}
// createdAt < [timestamp] AND createdAt > [timestamp]

{
  $or: [
    {
      title: {
        $like: 'Boat%'
      }
    },
    {
      description: {
        $like: '%boat%'
      }
    }
  ]
}
// title LIKE 'Boat%' OR description LIKE '%boat%'
CURD

create

result.dataValues;

========================

update

result [1];

========================

find - 從數據庫中查找一個指定元素

- findById 按已知id查找

- findOne 按屬性查找

result.dataValues

========================

findOrCreate - 從數據庫中查找一個指定元素若是不存在則建立記錄

========================

findAndCountAll - 從數據庫中查找多個元素,返回數據與記錄總數

count - 整數,匹配到的總記錄數
rows - 對象數據,經過 limit 和 offset匹配的當前頁數據

{ count: 0, rows: [] }

findAndCountAll一樣支持使用include包含,使用包含時只有將required設置爲true纔會添加到count部分:
User.findAndCountAll({
  include: [
     { model: Profile, required: true}
  ],
  limit: 3
});

使用include時,兩個模型之間應該存在主/外鍵關係,若是不存在就應該在include中手工創建鏈接。

在上面的示例中,爲Profile設置了required,因此在查詢時會使用INNER JOIN內鏈接。
========================

findAll - 從數據庫中查找多個元素

// 查詢時使用字符串替換
Project.findAll({ where: ["id > ?", 25] }).then(function(projects) {
  // projects 是一個包含 Project 實例的數組,各實例的id 大於25
})
========================

count - 統計數據庫中的元素數

max - 查找指定表中最大值

min - 查找指定表中最小值

sum - 對指定屬性求和

========================

destroy

result

項目實戰(提早了解,後面能夠再學到controller那一層的時候看代碼學習使用)

新增

clipboard.png

更新

clipboard.png

clipboard.png

查詢單個

clipboard.png

查詢所有 模糊查詢、分頁、排序

clipboard.png

相關文章
相關標籤/搜索