使用 Mongondb
zKing 2018-11-28 Koa
- 关于 Mongondb,此处不会去讲如何配置,而是讲解对 Mongondb 的连接与操作,这里用
mongoose
来进行示例 - 当前 mongoose 的使用版本为: "^5.3.12",献上文档
# ObjectId
存储在mongodb集合中的每个文档(document)都有一个默认的主键_id,这个主键名称是固定的,它可以是mongodb支持的任何数据类型,默认是ObjectId。
ObjectId是一个12字节的 BSON 类型字符串。按照字节顺序,依次代表:
- 4字节:UNIX时间戳
- 3字节:表示运行MongoDB的机器
- 2字节:表示生成此_id的进程
- 3字节:由一个随机数开始的计数器生成的值
# 快速上手
cnpm install mongoose -D
Mongoose 里,最核心的就是 Schema 和 Model Schema 用来定义了一个集合中数据的基本格式 Model 则是用来控制数据的
# MongoDb 没有表的情况
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
console.log('connect success');
var Schema = mongoose.Schema;
var newSchema = new Schema({
username: String,
password: String
})
var myCollect = mongoose.model("myCollect", newSchema);
new myCollect({
username:'test',
password:'123'
}).save(function(err,res){
console.log("save success");
});
myCollect.find(function (err, res) {
if (err) return console.error(err);
console.log(res)
});
});
# MongoDb 中已经建好表的情况下
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/test');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
console.log('connect success');
var Schema = mongoose.Schema;
var newSchema = new Schema({})
var myCollect = mongoose.model("myCollect", newSchema,"myCollect"); // 第三个参数要填已经建好的表名
myCollect.find(function (err, res) {
if (err) return console.error(err);
console.log(res)
});
});
# 实战示例
在学处理路由的时候做了个控制层的分层,现在就做一下模型层的分层来进行优化吧
优化后的目录如下:
project
├─app.js
|—db-config.js ------------ 存放数据库的相关配置
├─package.json
|—services
| ├─usersServices.js ------------ 存放数据表的CURD操作
|—models
| ├─usersModel.js ------------- 存放 Schema 模型
| └ index.js -------------- 导出 Model
|—controllers
| ├─model.js
| └ index.js
app.js
const Koa = require("koa");
const koaBody = require("koa-body");
const Router = require("koa-router");
const controllers=require("./controllers");
const router = new Router();
const app = new Koa();
require('./db-config');
app.use(koaBody());
app.use(controllers(router));
app.use(router.allowedMethods());
app.listen(3000, () => {
console.log("http://localhost:3000");
});
db-config.js
const mongoose = require('mongoose')
var dbUrl = 'mongodb://localhost:27017/myDB'
mongoose.connect(dbUrl, {
useNewUrlParser: true,
useCreateIndex: true
})
mongoose.connection.on('disconnected', () => {
mongoose.connect(dbUrl, {
useNewUrlParser: true,
useCreateIndex: true
})
})
mongoose.connection.on('error', err => {
console.error(err)
})
mongoose.connection.once('open', () => {
console.log('Connected to MongoDB -> ', dbUrl)
})
models/index.js
const UsersModel = require('./usersModel')
module.exports = {
UsersModel
}
models/usersModel.js
const mongoose = require('mongoose')
mongoose.Promise = global.Promise
const Schema = mongoose.Schema
const newSchema = new Schema({
username: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true
}
})
const UsersModel = mongoose.model('UsersModel', newSchema, 'users')
module.exports = UsersModel
services/usersServices.js
const { UserModel } = require('../models')
exports.findOneUser = async (params) => {
let resObj = await UserModel.findOne(params)
return resObj
}
exports.insertOneUser = async (params) => {
let user = new UserModel(params)
let resObj
try {
resObj = await user.save()
} catch (err) {
resObj = null
}
return resObj
}
exports.updateUser = async (condition, params) => {
let resObj
await UserModel.updateOne(condition, params, function (err, res) {
if (err) return console.error(err)
resObj = res
})
return resObj
}
exports.deleteUser = async (params) => {
let resObj
await CollectModel.deleteOne(params, function (err, res) {
if (err) return console.error(err)
resObj = res
})
return resObj
}
// 更新记录并返回查询的对象
exports.updateAndReturn = async (condition, params) => {
let resObj = await NewsModel.findOneAndUpdate(condition, params, { new: true })
return resObj
}
// 实现分页查询,一次查询 15 条数据,并降序排列
exports.findUsers = async (params, page) => {
let resObj = await NewsModel.find(params).skip(page * 15).limit(15).sort({ _id: -1 }).exec()
return resObj
}
controllers/model.js
const { findOneUser } = require('../services/usersServices')
const index = async (ctx, next) => {
ctx.type = "text/html";
ctx.body = `<h1>Index</h1>
<form action="/signin" method="post">
<p>Name: <input name="name" value="koa"></p>
<p>Password: <input name="password" type="password"></p>
<p><input type="submit" value="Submit"></p>
</form>`;
};
const login = async (ctx, next) => {
var body = ctx.request.body
var paramsObj = {
username: body.username,
password: body.password
}
let res = await findOneUser(paramsObj)
if (res === null) {
res = {status: false}
}
ctx.response.body = JSON.stringify(res)
}
module.exports = {
index,
login
}
controllers/index.js
const model = require("./model");
module.exports = (router) => {
router.get("/", model.index);
router.post("/login", model.login);
return router.routes();
}
讲解一下思路
- 通过
models
来进行模型定义并导出给services
来使用 controllers
通过services
来处理数据操作- 最后在
app.js
中引入db-config.js
和controllers
- 到此为止,就简单地以 Koa 为基础,形成一个简单地
Model-Control
模型
# 遇到的问题和解决方案
# 关于mongoose返回的数据无法修改的原因以及解决方法
原因
实际上mongoose返回的数据并不是object,虽然通过typeof判断类型是Object,但其实mongoose自己封装的一个对象,并且这个对象会对数据进行实时查询以保证其符合预定义的model,而无论添加删除model都不会改变,所以设置无效。
解决方法
在返回的result对象调用toObject()或toJSON()方法,则可以对它进行修改。
let res = await findOneUser()
let resJSON = JSON.stringify(res)
let resObj = JSON.parse(resJSON) // 获取到这个对象即可进行操作