egg基础功能2 -- egg操作mongodb

egg操作Mongodb

今天将给大家带来通过egg连接mongodb的相关总结,具体包括:

  • egg如何连接mongodb
  • 通过保存数据验证连接mongodb是成功的

egg连接mongodb

  • 1、 我们通过插件“egg-mongoose”连接mongodb数据库,我们先安装好插件:
npm i --save egg-mongoose

首先,我们通过egg的脚手架的方式创建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了。下面来验证一下连接!

验证连接

准备工作: 创建集合对象

'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'
  );
};

我们可以先去数据库中查看相关数据情况, 可以看到:目前仅仅只有user集合,且集合中无数据:


此外,我们在app/目录下创建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 's get method!");
  }

  /**
     * 分页返回数据
     * @param {Object} option 查询参数
     * @param {String} next 下一条数据的id
     * @param {Number} limit 一页包含多少数据
     * @param {Array} includs 返回数据包含字段数组,为空返回全部字段
     */
  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 };
  }

  /**
     * 分页返回数据
     * @param {Object} option 查询参数
     * @param {number} next 下一条数据的id
     * @param {Number} limit 一页包含多少数据
     * @param {Object} sort 排序
     * @param {Array} includs 返回数据包含字段数组,为空返回全部字段
     */
  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 查询参数
     * @param {Array} includs 返回数据包含字段数组,为空返回全部字段
     * @return {Array} 查询结果
     */
  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;

保存数据,验证连接成功

  • 1、我们在app/controller/目录下定义UserController.js,并且包含add()接口,接收user_name, age参数信息,调用UserService完成对user数据的保存。
'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、创建app/service目录,创建UserService.js,接收Controller传输过来的数据,完成对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}
   */
  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调用接口,完成保存


  • 5、调用接口,异常现象解决
    在第4步,我们直接调用postman之后,程序会发生异常。异常如下:


这是因为egg的csrf防范的安全,我们在config.default.js中添加如下代码即可解决:

config.security = {
   csrf: {
     enable: false,
     ignoreJSON: true,
   },
   domainWhiteList: [ '*' ],
 };
  • 6、 正常调用结果:

postman:


console控制台:


image.png

mongo数据库:


至此,我们完成了egg连接mongodb步骤。后面将详细总结egg+mongo的增删改查及多数据源情况下的配置。

你可能感兴趣的:(egg基础功能2 -- egg操作mongodb)