node(express,mongoose)写一个查询列表接口

1,494 阅读4分钟

前言

要用到express和mongoose

项目目录结构(选)

* bin/www 启动运行(服务端口设置等)
* app.js 整个项目的入口文件
* routes 对各个路由做处理的代码逻辑
* models 数据库的常用操作及配置



app.js文件代码解读


app对象的功能:

是为了使用一些具有特定功能的函数( 这些函数我们给起了一个名字 , 叫做中间件 )

 我们通过app.use(两个参数:路径,回调) 来使用这些中间件

var index = require('./routes/index'); // 声明要访问的路由

var app = express(); // 重要
app.use('/', index); // 访问已定义的路由文件

module.exports = app; // 抛出 app 变量方法(为 bin 中端口设置做准备)

再来看看bin文件夹

// bin/invoice-server

/**
 * Normalize a port into a number, string, or false.
 */
function normalizePort(val) {
  const port = parseInt(val, 10);
  if (isNaN(port)) {
    return val;
  }
  if (port >= 0) {
    return port;
  }
  return false;
}

/**
 * Event listener for HTTP server "error" event.
 */
function onError(error) {
  if (error.syscall !== 'listen') {
    throw error;
  }

  const bind = typeof port === 'string'
    ? 'Pipe ' + port
    : 'Port ' + port;

  // handle specific listen errors with friendly messages
  switch (error.code) {
    case 'EACCES':
      console.error(bind + ' requires elevated privileges');
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(bind + ' is already in use');
      process.exit(1);
      break;
    default:
      throw error;
  }
}

/**
 * Event listener for HTTP server "listening" event.
 */
function onListening() {
  const addr = server.address();
  const bind = typeof addr === 'string'
    ? 'pipe ' + addr
    : 'port ' + addr.port;
  debug('Listening on ' + bind);
}

// ~~~ 前面都不用改动 ~~~

/**
 * Module dependencies.
 */
const app = require('../app'); // 与前面说的“抛出 app 变量方法(为 bin 中端口设置做准备)”呼应
const debug = require('debug')('server:server'); // 为项目添加DEBUG环境变量,其中第一个server为我们设置 DEBUG 环境变量的值
const http = require('http'); // 提供 httpServer 服务模块,不可少

/**
 * Get port from environment and store in Express.
 */
const port = normalizePort(process.env.PORT || '8976'); // 声明端口, 不可少
app.set('port', port); // 绑定端口

/**
 * Create HTTP server.
 */

const server = http.createServer(app); // 使用 定义的 http 服务, 不可少

/**
 * Listen on provided port, on all network interfaces.
 */

server.listen(port); // 监听端口
server.on('error', onError);
server.on('listening', onListening);

express作用

是Node.js的核心框架,可以帮助我们快速构建web服务器 / api服务器

Express相对于原生的http模块提供了2个核心功能:静态文件 | 路由处理

mongoose作用

mongoose是nodeJS提供连接 mongodb的一个库


写一个查询接口

mongoose连接数据库

2. models中用mongoose的schema和model操作数据库

定义一个schema
Mongoose 的一切始于 Schema

每个 schema 都会映射到一个 MongoDB collection ,并定义这个collection里的文档的构成

Models
Models 是从 Schema 编译来的构造函数。 它的实例就是可以从数据库保存和读取的文档。

从数据库创建和读取 document 的所有操作都是通过 model 进行的。

PS:schema和model可以理解为继承的关系


简单的示例:

var schema = new mongoose.Schema({ name: 'string', size: 'string' });
var Tank = mongoose.model('Tank', schema); // 把 schema 转换为一个 Model(创建Model) 
  • 第一个参数是跟 model 对应的集合( collection )名字的 单数 形式, Mongoose 会自动找到名称是 model 名字 复数 形式的 collection
  • demo中Tank 这个 model 就对应数据库中 tanks 这个 collection
  • .model() 这个函数其实是对 schema 做了拷贝(生成了 Model)


关于model()方法的第三个参数,可能会遇到一点坑(终端上访问数据库可能会没有相关的collection)

查阅了官方文档才知道,当没有传递collection参数时,Mongoose通过将模型名称传递给utils.toCollectionName方法来生成集合名称,可以通过下面文档给出的demo设置自己的schema集合名称:


3.  routes里用express+mongoose具体实现查询

//查询列表
router.post("/list", function (req, res, next) {
  const {
    pageNum,
    pageSize,
    _userinfo = {},
    ...rest
  } = req.body;
  const params = { ...rest }; // 查询参数
  const skip = (pageNum - 1) * pageSize; // 第pageNum页开始记录条数
  
  // .find(conditions, [projection], [options], [callback]) 查找文档
  // 在发送命令之前,将conditions参数(条件)转换为各自的模式类型
  const model = Configs.find(params).skip(skip).limit(pageSize);
  const sortConfig = {
      createAt: -1
  };
  model.sort(sortConfig);
  model.exec(function (err, doc) { // .exec() 明确查询结果,第一个参数永远是err,第二个参数是返回的数据
    if (err) {
      res.json({
        success: false,
        msg: err.message
      });
    } else {
      // .aggregate([pipeline], [callback]) 对Model集合执行聚合,也就是重整
      // pipeline 是一个数组  将管道聚合为对象数组
      // aggregate()不触发任何中间件
      Configs.aggregate([
        {
          $match: {...params} // 条件筛选关键词
        },
        {
          $group: { // 分组
            _id: null,
            total: { $sum: 1 }
          }
        }
      ], function (err2, doc2) { // 参数callback如果传递回调,则执行聚合并返回Promise;如果没有传递回调,则返回聚合本身。
        Configs.find({}, function (err3, doc3) {
          if(err){
            res.json({
              success: false,
              msg: err.message
            });
          } else {
            if (err2) {
              res.json({
                success: false,
                msg: err2.message
              });
            } else {
              res.json({
                success: true,
                msg:'',
                result:{
                  list: doc, // doc打印结果见下面的图
                  pageNum,
                  total: doc2[0] ? doc2[0].total : 0
                }
              });
            }
          }
        })
      });
    }
  });
});
打印一下req.body,可以看到前端发过来的请求数据:


浏览器中向后端发送的确实也是这些数据:


doc打印结果:


也即数据库里存储的数据: