egg基礎(chǔ)功能2 -- egg操作mongodb

egg操作Mongodb

今天將給大家?guī)硗ㄟ^egg連接mongodb的相關(guān)總結(jié),具體包括:

  • egg如何連接mongodb
  • 通過保存數(shù)據(jù)驗證連接mongodb是成功的

egg連接mongodb

  • 1油猫、 我們通過插件“egg-mongoose”連接mongodb數(shù)據(jù)庫荤堪,我們先安裝好插件:
npm i --save egg-mongoose

首先寺谤,我們通過egg的腳手架的方式創(chuàng)建egg工程,這一步不再細述,請參閱之前的文章凌彬。

  • 2、 添加egg-mongoose 插件:在egg工程的config/plugin.js中添加插件egg-mongoose:
'use strict';

/** @type Egg.EggPlugin */
module.exports = {
  mongoose: {
    enable: true,
    package: 'egg-mongoose',
  },
};
  • 3循衰、 添加mongodb的連接信息: 在config/config.default.js中添加mongodb的連接信息:
/* eslint valid-jsdoc: "off" */

'use strict';

/**
 * @param {Egg.EggAppInfo} appInfo app info
 */
module.exports = appInfo => {
  /**
   * built-in config
   * @type {Egg.EggAppConfig}
   **/
  const config = exports = {};

  // use for cookie sign key, should change to your own and keep security
  config.keys = appInfo.name + '_1564639326024_3672';

  // add your middleware config here
  config.middleware = [];

  // 連接mongodb的配置
  config.mongoose = {
    client: {
      url: 'mongodb://127.0.0.1/jianshu',
      options: {},
    },
  };

  // config.cluster = {
  //   listen: {
  //     port: 9999,
  //   },
  // };

  // add your user config here
  const userConfig = {
    // myAppName: 'egg',
  };

  return {
    ...config,
    ...userConfig,
  };
};

到這里铲敛,我們就可以通過egg連接mongodb了。下面來驗證一下連接会钝!

驗證連接

準備工作: 創(chuàng)建集合對象

'use strict';

module.exports = app => {
  const { mongoose } = app;

  return mongoose.model(
    'User',
    new mongoose.Schema({
      user_id: { type: String, unique: true },
      user_name: { type: String },
      age: { type: Number },
      description: { type: String },
      status: { type: Number },
    }),
    'user'
  );
};

我們可以先去數(shù)據(jù)庫中查看相關(guān)數(shù)據(jù)情況伐蒋, 可以看到:目前僅僅只有user集合,且集合中無數(shù)據(jù):


此外迁酸,我們在app/目錄下創(chuàng)建core目錄先鱼,并封裝BaseController和BaseService:

'use strict';

const { Controller } = require('egg');

class BaseController extends Controller {
  async returnService(promise) {
    const [ error, data ] = await this.wapperError(promise);
    if (error) {
      this.error(error);
    } else {
      this.success(data);
    }
  }

  success(data) {
    this.ctx.body = { status: 'OK', data };
  }

  error(error) {
    this.ctx.body = { status: 'NG', error: error.message || error };
  }

  wapperError(promise) {
    return promise
      .then(data => {
        return [ undefined, data ];
      })
      .catch(err => [ err ]);
  }
}
module.exports = BaseController;

'use strict';

const Service = require('egg').Service;

class BaseMongooseService extends Service {
  get document() {
    throw Error("BaseMongooseService need override property <document>'s get method!");
  }

  /**
     * 分頁返回數(shù)據(jù)
     * @param {Object} option 查詢參數(shù)
     * @param {String} next 下一條數(shù)據(jù)的id
     * @param {Number} limit 一頁包含多少數(shù)據(jù)
     * @param {Array} includs 返回數(shù)據(jù)包含字段數(shù)組,為空返回全部字段
     */
  async page(option, next, limit, includs, sort) {
    limit = limit || 50;
    const findLimit = limit + 1;
    const projection = {};
    if (includs && includs instanceof Array) {
      includs.forEach(item => {
        projection[item] = 1;
      });
    }
    if (next) {
      option._id = { $lte: next };
    }

    // const sortPrama ={ _id : -1 } ;
    const sortPrama = (sort ? sort : { _id: -1 });
    const data = await this.document
      .find(option, projection)
      .sort(sortPrama)
      .limit(findLimit);

    if (data.length === findLimit) {
      return { next: data.pop()._id, data, total: data.length };
    }
    return { data, total: data.length };
  }

  /**
     * 分頁返回數(shù)據(jù)
     * @param {Object} option 查詢參數(shù)
     * @param {number} next 下一條數(shù)據(jù)的id
     * @param {Number} limit 一頁包含多少數(shù)據(jù)
     * @param {Object} sort 排序
     * @param {Array} includs 返回數(shù)據(jù)包含字段數(shù)組奸鬓,為空返回全部字段
     */
  async pageList(option, next, limit, includs, sort) {
    limit = limit || 50;
    next = parseInt(next) || 1;
    const projection = {};
    if (includs && includs instanceof Array) {
      includs.forEach(item => {
        projection[item] = 1;
      });
    }

    if (!sort) { throw Error('sort is not find '); }
    const data = await this.document
      .find(option, projection).skip((next - 1) * limit)
      .sort(sort)
      .limit(limit);
    return { next: (next + 1), data, total: data.length };
  }

  /**
     * 查詢
     * @param {Object} option 查詢參數(shù)
     * @param {Array} includs 返回數(shù)據(jù)包含字段數(shù)組焙畔,為空返回全部字段
     * @return {Array} 查詢結(jié)果
     */
  async find(option, includs) {
    const projection = {};
    if (includs && includs instanceof Array) {
      includs.forEach(item => {
        projection[item] = 1;
      });
    }
    return await this.document.find(option, projection);
  }
  async findById(_id, includs) {
    return await this.document.findOne({ _id }, includs);
  }
  async findOne(option, includs) {
    const projection = {};
    if (includs && includs instanceof Array) {
      includs.forEach(item => {
        projection[item] = 1;
      });
    }
    return await this.document.findOne(option, projection).orFail();
  }

  async create(detail) {
    // const Document = this.document;
    const now = new Date().getTime();
    const _create = {
      create_stamp: now,
      update_stamp: now,
    };
    return await new this.document(Object.assign(_create, detail)).save();
  }

  async update(option, detail) {
    const now = new Date().getTime();
    const _update = {
      update_stamp: now,
    };
    await this.document.updateOne(option, Object.assign(_update, detail)).orFail();
  }
  async updateById(_id, detail) {
    return await this.update({ _id }, detail);
  }


}

module.exports = BaseMongooseService;

保存數(shù)據(jù),驗證連接成功

  • 1串远、我們在app/controller/目錄下定義UserController.js宏多,并且包含add()接口,接收user_name, age參數(shù)信息澡罚,調(diào)用UserService完成對user數(shù)據(jù)的保存绷落。
'use strict';

const Controller = require('../core/BaseController');

class UserController extends Controller {

  async add() {
    const { userService } = this.ctx.service;
    const { user_name, age } = this.ctx.request.body;
    console.log('Received: user_name = ' + user_name + ', age = ' + age);

    await this.returnService(userService.add(user_name, age));
  }
}

module.exports = UserController;

  • 2、創(chuàng)建app/service目錄始苇,創(chuàng)建UserService.js砌烁,接收Controller傳輸過來的數(shù)據(jù),完成對user的保存。
'use strict';

const Service = require('../core/BaseMongooseService');
const uuidv1 = require('uuid/v1');

class UserService extends Service {
  get document() {
    return this.ctx.model.User;
  }

  /**
   * 添加用戶
   * @param user_name
   * @param age
   * @returns {Promise<void>}
   */
  async add(user_name, age) {
    const { User } = this.ctx.model;
    const userMap = new User();
    userMap.user_name = user_name;
    userMap.age = age;
    userMap.user_id = uuidv1();
    userMap.description = '用戶';
    userMap.status = 0;

    userMap.save();
  }
}
module.exports = UserService;

  • 3函喉、定義路由:在router.js下定義add接口的路由:
router.post('/add', controller.userController.add);
  • 4避归、使用postman調(diào)用接口,完成保存


  • 5管呵、調(diào)用接口梳毙,異常現(xiàn)象解決
    在第4步捐下,我們直接調(diào)用postman之后账锹,程序會發(fā)生異常。異常如下:


這是因為egg的csrf防范的安全坷襟,我們在config.default.js中添加如下代碼即可解決:

config.security = {
   csrf: {
     enable: false,
     ignoreJSON: true,
   },
   domainWhiteList: [ '*' ],
 };
  • 6奸柬、 正常調(diào)用結(jié)果:

postman:


console控制臺:


image.png

mongo數(shù)據(jù)庫:


至此,我們完成了egg連接mongodb步驟婴程。后面將詳細總結(jié)egg+mongo的增刪改查及多數(shù)據(jù)源情況下的配置廓奕。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市档叔,隨后出現(xiàn)的幾起案子桌粉,更是在濱河造成了極大的恐慌,老刑警劉巖衙四,帶你破解...
    沈念sama閱讀 221,331評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铃肯,死亡現(xiàn)場離奇詭異,居然都是意外死亡传蹈,警方通過查閱死者的電腦和手機缘薛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,372評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來卡睦,“玉大人宴胧,你說我怎么就攤上這事”矶停” “怎么了恕齐?”我有些...
    開封第一講書人閱讀 167,755評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瞬逊。 經(jīng)常有香客問我显歧,道長,這世上最難降的妖魔是什么确镊? 我笑而不...
    開封第一講書人閱讀 59,528評論 1 296
  • 正文 為了忘掉前任士骤,我火速辦了婚禮,結(jié)果婚禮上蕾域,老公的妹妹穿的比我還像新娘拷肌。我一直安慰自己到旦,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,526評論 6 397
  • 文/花漫 我一把揭開白布巨缘。 她就那樣靜靜地躺著添忘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪若锁。 梳的紋絲不亂的頭發(fā)上搁骑,一...
    開封第一講書人閱讀 52,166評論 1 308
  • 那天,我揣著相機與錄音又固,去河邊找鬼仲器。 笑死,一個胖子當(dāng)著我的面吹牛仰冠,可吹牛的內(nèi)容都是我干的乏冀。 我是一名探鬼主播,決...
    沈念sama閱讀 40,768評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼沪停,長吁一口氣:“原來是場噩夢啊……” “哼煤辨!你這毒婦竟也來了裳涛?” 一聲冷哼從身側(cè)響起木张,我...
    開封第一講書人閱讀 39,664評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎端三,沒想到半個月后舷礼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,205評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡郊闯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,290評論 3 340
  • 正文 我和宋清朗相戀三年妻献,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片团赁。...
    茶點故事閱讀 40,435評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡育拨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出欢摄,到底是詐尸還是另有隱情熬丧,我是刑警寧澤,帶...
    沈念sama閱讀 36,126評論 5 349
  • 正文 年R本政府宣布怀挠,位于F島的核電站析蝴,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏绿淋。R本人自食惡果不足惜闷畸,卻給世界環(huán)境...
    茶點故事閱讀 41,804評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吞滞。 院中可真熱鬧佑菩,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,276評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凸舵,卻和暖如春祖娘,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背啊奄。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工渐苏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人菇夸。 一個月前我還...
    沈念sama閱讀 48,818評論 3 376
  • 正文 我出身青樓琼富,卻偏偏與公主長得像,于是被迫代替她去往敵國和親庄新。 傳聞我的和親對象是個殘疾皇子鞠眉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,442評論 2 359

推薦閱讀更多精彩內(nèi)容