mongoose

什么是mongoose

Mongoose库简而言之就是对node环境中MongoDB数据库操作的封装,一种对象模型工具,可以将数据库中的数据转换为JavaScript对象供我们使用。

用到的工具

  • Vue-Cli
  • Vue-Resource
  • Node+Express
  • MongoDB

MongoDB下载、安装、启用

  • 默认mongoDB安装完毕(D盘)
  • mongo-data文件夹放置mongoDB数据(D盘)
  • mongo-data文件夹下新建db文件夹
  • 进入mongoDB目录
  • 进入bin目录
  • 键入mongod.exe -dbpath d:\mongo-data\db命令

整体目录结构

    ├─build
    ├─config
    ├─dist
    ├─node_modules
    └─server          # Node相关
       └─json
       └─api.js        # 编写接口
       └─db.js         #设置数据库相关
       └─express.js
       └─index.js      #入口文件
    ├─src
    ├─static
    ├─test
    ├─...
    ├─...

db.js

// Schema、Model、Entity或者Documents的关系请牢记,Schema生成Model,Model创造Entity,Model和Entity都可对数据库操作造成影响,但Model比Entity更具操作性。
const mongoose = require('mongoose')
// 连接数据库 如果不自己创建 默认test数据库会自动生成
mongoose.connect('mongodb://localhost/test')

// 为这次连接绑定事件
const db = mongoose.connection
db.once('error', () => console.log('Mongo connection error'))
db.once('open', () => console.log('Mongo connection successed'))
/** ************ 定义模式loginSchema **************/
const loginSchema = mongoose.Schema({
  account: String,
  password: String
})

/** ************ 定义模式phoneSchema **************/
const phoneSchema = mongoose.Schema({
  device: String, // 设备名称
  isSmart: Boolean, // 是否为智能手机
  releaseTime: Date, // 发布时间
  price: Number, // 售价
  apps: [{name: String}], // 手机中安装的App名称,是数组
  manufacturer: { // 手机厂商
    name: String, // 厂商名称
    country: String // 厂商国籍
  }
})
// 动态扩展
phoneSchema.add({color: 'string'})

// 为Model的实例添加自定义方法(将自定义的方法添加到Schema.methods即可)
phoneSchema.methods.printBrief = function () {
  // console.log(this)
  console.log('手机+价格' + this.device, '¥' + this.price)
}

// 为Model添加静态方法
phoneSchema.statics.printCount = function () {
  // 进行计数
  this.count({}, (err, count) => {
    console.log('----printCount()-----------')
    if (err) {
      console.log(err)
    } else {
      console.log('phone count=' + count)
    }
  })
}

/** ************ 定义模型Model **************/
const Models = {
  Login: mongoose.model('Login', loginSchema),
  Phone: mongoose.model('Phone', phoneSchema)
}

module.exports = Models

api.js

// 可能是我的node版本问题,不用严格模式使用ES6语法会报错
'use strict'
const models = require('./db')
const express = require('express')
const router = express.Router()

/** ************ 创建(create) 读取(get) 更新(update) 删除(delete) **************/

// 创建账号接口
router.post('/api/login/createAccount', (req, res) => {
  console.log(req.body)
  // 这里的req.body能够使用就在index.js中引入了const bodyParser = require('body-parser')
  let newAccount = new models.Login({
    account: req.body.account,
    password: req.body.password
  })
  // 调用实例方法
  // newAccount.printBrief()
  // 保存数据newAccount数据进mongoDB
  newAccount.save((err, data) => {
    if (err) {
      res.send(err)
    } else {
      res.send('createAccount successed')
    }
  })
})

// 删除账号接口
router.post('/api/login/deleteAccount', (req, res) => {
  console.log(req.body.account)
  if (req.body.account === 'admin') {
    return
  }
  // 调用静态方法
  // models.Login.printCount()
  models.Login.remove({account: req.body.account}, (err, data) => {
    console.log('执行删除')
    if (err) {
      res.send(err)
    } else {
      res.send('deleteAccount successed')
    }
  })
})

// 修改账号接口
router.post('/api/login/updateAccount', (req, res) => {
  console.log(req.body.account)
  console.log(req.body.editorAccount)
  var conditions = {account: req.body.account}
  var update = {$set: {account: req.body.editorAccount}}
  var options = {upsert: true}
  console.log(conditions)
  console.log(update)
  console.log(options)
  models.Login.update(conditions, update, options, (err, data) => {
    console.log('执行修改')
    if (err) {
      res.send(err)
    } else {
      res.send('updateAccount successed')
    }
  })
})

// 登录
router.post('/api/login/login', (req, res) => {
  models.Login.find({account: req.body.account}, (err, data) => {
    // console.log('获取登录的用户数据')
    // console.log(!data)
    if (err) {
      res.send(err)
    } if (!data) {
      res.send(data)
    } else {
      // 匹配密码
      // if (req.body.account === undefined) {
      //   res.send(data)
      //   return
      // }
      // console.log(data)
      if (data.length === 0) {
        res.send({ret_code: 65535, ret_msg: '用户不存在'})
        return
      }
      if (req.body.password !== data[0].password) {
        res.send({ret_code: 404, ret_msg: '密码错误'})
      } else {
        console.log('用户名和密码已经匹配')
        // session start
        req.session.regenerate(function (err) {
          if (err) {
            res.send({ret_code: 2, ret_msg: '登录失败'})
          }
          req.session.loginUser = data[0].account
          res.send({ret_code: 0, ret_msg: '登录成功'})
          console.log(req.session)
        })
        // console.log('登陆成功')
        // res.send({ret_code: 0, ret_msg: '登录成功'})
      }
    }
  })
})

// 获取已有账号接口
router.post('/api/login/getAccount', (req, res) => {
  var params
  // console.log(req.body.account === undefined)
  // console.log('是的发送到')
  if (req.body.account === undefined) {
    params = {}
  } else {
    params = {account: req.body.account}
  }
  // console.log(req.body.account)
  // console.log(req.body.password)
  // 通过模型去查找数据库(直接查询)
  models.Login.find(params, (err, data) => {
    // console.log('获取登录的用户数据')
    // console.log(data)
    // console.log(!data)
    if (err) {
      res.send(err)
    } if (!data) {
      res.send(data)
    } else {
      // 匹配密码
      if (req.body.account === undefined) {
        res.send(data)
        return
      }
      // console.log(data)
      if (data.length === 0) {
        res.send('用户不存在')
        return
      }
      // console.log(data[0].password)
      if (req.body.password !== data[0].password) {
        // console.log('密码错误')
        res.send(404 + '密码错误')
      } else {
        // console.log('登陆成功')
        res.send(200 + '登陆成功' + data)
      }
    }
  })
})

// 获取手机列表接口
router.post('/api/login/getPhoneList', (req, res) => {
  models.Phone.find((err, data) => {
    console.log(data.length)
    if (err) {
      // console.log('err')
      res.send(err)
    } else {
      console.log('---findAllPhone---------------------------------------')
      res.send(data)
      // data.forEach((element, index, data) => {
      //   console.log(index, element)
      // })
    }
  })
})

// 根据价格排序方式查询手机列表
router.post('/api/login/priceSortList', (req, res) => {
  // console.log(req.body.sortVal)
  var sortWay
  if (req.body.sortVal === 'desc') {
    sortWay = {price: 'desc'}
  } else {
    sortWay = {price: 'asc'}
  }
  var query = models.Phone.find({})
  // query.sort('-price') // 高->低 (price)
  query.sort(sortWay) // 高->低(asc)
  // // query.sort({price: 'descending'}) // 高->低(ascending)
  // // query.sort({price: -1}) // 高->低(1)
  // // query.sort({price: -1}).limit(2) // 限制几条数据
  .exec((err, person) => {
    if (err) {
      console.log(err)
    } else {
      // console.log(person)
      res.send(person)
    }
  })
})

// 根据价格范围查询手机列表
router.post('/api/login/priceSelectList', (req, res) => {
  // console.log(req.body)
  models.Phone.find()
  .where('price').gte(parseInt(req.body.lowest)).lte(parseInt(req.body.highest))
  .exec((err, data) => {
    if (err) {
      res.send(err)
    } else {
      console.log('---findPrice_1000_4000Phone()---------------------------------------')
      res.send(data)
      data.forEach((element, index, data) => {
        console.log(index, element)
      })
    }
  })
})

// 是否为智能手机查询列表
router.post('/api/login/isSmartPhoneList', (req, res) => {
  console.log(req.body.value)
  models.Phone.find({isSmart: req.body.value}, (err, data) => {
    if (err) {
      res.send(err)
    } else {
      console.log('---findIsSmartPhone()---------------------------------------')
      res.send(data)
      data.forEach((element, index, data) => {
        console.log(index, element)
      })
    }
  })
})

module.exports = router

MONGOOSE

Schema(模式):一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力,,仅仅 只是一段代码,无法通往数据库端, 仅仅只是数据库模型在程序片段中的一种表现.
Model(模型):由Schema发布生成的模型(是经过Schema构造来的,是Schema的编译版本),具 有抽象属性和行为的数据库操作对.一个model的实例直接映射为数据库中的一个文档,基于这 种关系, 以后的增删改查(CURD)都要通过这个Model实现.
Entity:由Model创建的实体,他的操作也会影响数据库
Schema、Model、Entity的关系:Schema生成Model,Model创造Entity,Model和Entity都可对数据库操作造成影响,但Model比Entity更具操作性。

定义一个Schema:

const mongoose = require('mongoose')
// 连接数据库 如果不自己创建 默认test数据库会自动生成
mongoose.connect('mongodb://localhost/test')

// 为这次连接绑定事件
const db = mongoose.connection
db.once('error', () => console.log('Mongo connection error'))
db.once('open', () => console.log('Mongo connection successed'))
/** ************ 定义模式loginSchema **************/
const loginSchema = mongoose.Schema({
  account: String,
  password: String
})

将该Schema发布为Model:

/** ************ 定义模型Model **************/
const Models = {
  Login: mongoose.model('Login', loginSchema),
  Phone: mongoose.model('Phone', phoneSchema)
}

用Model创建Entity:

'use strict'
const models = require('./db')
const express = require('express')
const router = express.Router()

/** ************ 创建(create) 读取(get) 更新(update) 删除(delete) **************/

// 创建账号接口
router.post('/api/login/createAccount', (req, res) => {
  console.log(req.body)
  // 这里的req.body能够使用就在index.js中引入了const bodyParser = require('body-parser')
  let newAccount = new models.Login({
    account: req.body.account,
    password: req.body.password
  })
  // 调用实例方法
  // newAccount.printBrief()
  // 保存数据newAccount数据进mongoDB
  newAccount.save((err, data) => {
    if (err) {
      res.send(err)
    } else {
      res.send('createAccount successed')
    }
  })
})

Schema的扩展

/** ************ 定义模式phoneSchema **************/
const phoneSchema = mongoose.Schema({
  device: String, // 设备名称
  isSmart: Boolean, // 是否为智能手机
  releaseTime: Date, // 发布时间
  price: Number, // 售价
  apps: [{name: String}], // 手机中安装的App名称,是数组
  manufacturer: { // 手机厂商
    name: String, // 厂商名称
    country: String // 厂商国籍
  }
})

实例方法

-Model实例方法只能被Model的实例调用,不能被Model直接调用,否则会抛出 is not a function 异常

// 为Model的实例添加自定义方法(将自定义的方法添加到Schema.methods即可)
phoneSchema.methods.printBrief = function () {
  // console.log(this)
  console.log('手机+价格' + this.device, '¥' + this.price)
}

let newAccount = new models.Login({
    account: req.body.account,
    password: req.body.password
  })
  // 调用实例方法
  // newAccount.printBrief()

静态方法

// 为Model添加静态方法
phoneSchema.statics.printCount = function () {
  // 进行计数
  this.count({}, (err, count) => {
    console.log('----printCount()-----------')
    if (err) {
      console.log(err)
    } else {
      console.log('phone count=' + count)
    }
  })
}

// 调用静态方法
// models.Login.printCount()

增删改查(CURD)

增加

// 创建账号接口
router.post('/api/login/createAccount', (req, res) => {
  console.log(req.body)
  // 这里的req.body能够使用就在index.js中引入了const bodyParser = require('body-parser')
  // 用Model创建Entity
  let newAccount = new models.Login({
    account: req.body.account,
    password: req.body.password
  })
  // 保存newAccount数据进mongoDB
  newAccount.save((err, data) => {
    if (err) {
      res.send(err)
    } else {
      res.send('createAccount successed')
    }
  })
})

删除

// 删除账号接口
router.post('/api/login/deleteAccount', (req, res) => {
  console.log(req.body.account)
  if (req.body.account === 'admin') {
    return
  }
  // 调用remove方法
  models.Login.remove({account: req.body.account}, (err, data) => {
    console.log('执行删除')
    if (err) {
      res.send(err)
    } else {
      res.send('deleteAccount successed')
    }
  })
})

修改

// 修改账号接口 update
router.post('/api/login/updateAccount', (req, res) => {
  console.log(req.body.account)
  console.log(req.body.editorAccount)
  var conditions = {account: req.body.account}
  var update = {$set: {account: req.body.editorAccount}}
  var options = {upsert: true}
  console.log(conditions)
  console.log(update)
  console.log(options)
  models.Login.update(conditions, update, options, (err, data) => {
    console.log('执行修改')
    if (err) {
      res.send(err)
    } else {
      res.send('updateAccount successed')
    }
  })
})

查询

直接查询

在查询时带有回调函数的,称之为直接查询,查询的条件往往通过API来设定

// 通过模型去查找数据库
  models.Login.find({account: req.body.account}, (err, data) => {
    // console.log('获取登录的用户数据')
    // console.log(!data)
    if (err) {
      res.send(err)
    } if (!data) {
      res.send(data)
    } else {
      // 匹配密码
      // if (req.body.account === undefined) {
      //   res.send(data)
      //   return
      // }
      // console.log(data)
      if (data.length === 0) {
        res.send({ret_code: 65535, ret_msg: '用户不存在'})
        return
      }
      // console.log(data)
      // console.log(data.account, req.body.account)
      // console.log(data.password, req.body.password)
      // if (data.account === req.body.account && data.password === req.body.password) {
      //   console.log('用户名和密码已经匹配')
      // } else {
      //   console.log('用户名或密码不正确')
      // }
      // console.log(data[0].password)
      if (req.body.password !== data[0].password) {
        res.send({ret_code: 404, ret_msg: '密码错误'})
      } else {
        console.log('用户名和密码已经匹配')
        // session start
        req.session.regenerate(function (err) {
          if (err) {
            res.send({ret_code: 2, ret_msg: '登录失败'})
          }
          req.session.loginUser = data[0].account
          res.send({ret_code: 0, ret_msg: '登录成功'})
          console.log(req.session)
        })
        // console.log('登陆成功')
        // res.send({ret_code: 0, ret_msg: '登录成功'})
      }
    }
  })

链式查询

在查询时候,不带回调,而查询条件通过API函数来制定

  // 链式查询
  console.log(models.Login)
  var query = models.Login.find({})
  query.select('some select') // 列表中只保留id
  query.select('occupation') // 列表中只保留id
  query.select('account occupation') // 列表中保留id + account
  query.select('password occupation') // 列表中保留id + password
  query.select('account password occupation') // 列表中保留id + account + password
  query.where('account').equals('aaa')
  query.sort('-occupation')
  // 有时我们需要在 MongoDB 中使用 JavaScript 表达式进行查询,
  // 这时可以用 find({$where : javascript}) 方式,$where 是一种快捷方式,并支持链式调用查询
  query.$where("this.account === 'aaa'")
  query.exec((err, person) => {
    console.log(err + '错误')
    console.log(person)
  })

学习连接

  1. http://openlayers.org/
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值