什么是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)
})