美文网首页
egg基础功能2 -- egg操作mongodb

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

作者: 卡布奇诺_flygrk | 来源:发表于2019-08-15 15:15 被阅读0次

    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 <document>'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<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调用接口,完成保存


    • 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

          本文链接:https://www.haomeiwen.com/subject/eqrzjctx.html