安装mongodb
- https://www.mongodb.com/ 进行安装
- 将mongodb的bin 目录添加到系统环境变量
// 启动mongdb 数据库
//E:\works\vueNodeMongoose\server\db :db文件夹所在的位置
`mongod --dbpath=E:\works\vueNodeMongoose\server\db --port=27019`
Robt (mongoose数据可视化工具)
- https://robomongo.org/download 下载安装
- 连接对应数据库地址、端口
连接数据库
//加载数据库模块
var mongoose = require('mongoose');
//链接`数据库
mongoose.connect('mongodb://localhost:27018/blog',{useNewUrlParser:true},function(err){
//URL以mongodb:// + [用户名:密码@] +数据库地址[:端口] + 数据库名。(默认端口27017)
if(err){
console.log('数据库连接失败')
}else{
console.log('数据库连接成功')
app.listen(8081);
}
});
基本概念
mongoose英文api 尽量看英文文档 中文里边有的方法已经被替换了
mongoose中文api
Schema
用来定义数据库文档结构,数据库有什么字段、字段是什么类型、默认值、主键之类的信息。除了定义结构外,还能定义文档的实例方法,静态模型方法,复合索引,中间件等。每个schema会映射到mongodb中的一个collection,schema不具备操作数据库的能力
Model
是将Schema定义的结构赋予表名。但可用此名对数据库进行增删查改。
Entity
是将Model与具体的数据绑定,可以对具体数据自身进行操作,例如保存数据。
Schema、 model
Schema.Type
是Mongoose内部定义的数据类型。基本类型有:String
、Number
、Date
、Boolean
、Array
、Buffer
、Mixed
、ObjectId
//model文件下新建user.js
var mongoose = require('mongoose');
let userSchema=new mongoose.Schema({
username:String,
password: String,
isAdmin:{
type:Boolean,
default:false
},
createTime:{
type: Date,
default:Date.now()
},
})
let userModel=mongoose.model('User',userSchema);
增查改删
增
单条增加:Model.create(doc(s), (err,docs)=>{})
单条增加:new Model(doc).save((err,docs)=>{})
多条增加:Model.insertMany(doc(s), [options], [callback])
//1.
userModel.create(
{username:'zhanglibing',password: '123456'},
(err,docs)=>{
if(err) console.log(err);
console.log('保存成功:' + doc);
}
)
//2.
new userMode({username:'zhanglibing',password: '123456'}).save((err,docs)=>{
if(err) console.log(err);
console.log('保存成功:' + doc);
})
//3.
userModel.insertMany(
[
{username:'zhanglibing',password: '123456'},
{username:'zhanglibing1',password: '123456'},
],
(err,docs)=>{
if(err) console.log(err);
console.log('保存成功:' + doc);
}
)
删
Model.remove({ _id: 1 }, callback)
Model.deleteOne({ name: 'Eddard Stark' }, callback)
(callback可用.then .catch替换)
删除多条 Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, callback)
(callback可用.then .catch替换)
改
- 1.
Model.update(conditions, doc, [options], [callback])
- 2.
Model.updateMany
(conditions, doc, [options], [callback])
conditions
:查询条件;doc
:需要修改的数据,不能修改主键(_id);options
:控制选项;callback
:回调函数,返回的是受影响的行数。
options
有以下选项:
safe (boolean): 默认为true。安全模式。
upsert (boolean): 默认为false。如果不存在则创建新记录。
multi (boolean): 默认为false。是否更新多个查询记录。
runValidators: 如果值为true,执行Validation验证。
setDefaultsOnInsert: 如果upsert选项为true,在新建时插入文档定义的默认值。
strict (boolean): 以strict模式进行更新。
overwrite (boolean): 默认为false。禁用update-only模式,允许覆盖记录
userModel.update({_id: 1}, {username: "test" ...}, {multi: true}, function(err, docs){
if(err) console.log(err);
console.log('更改成功:' + docs);
})
查
Model.findOne
(conditions, [projection], [options], [callback])
Model.findById
(id, [projection], [options], [callback])
Model.find
(conditions, [projection], [options], [callback])
- projection过滤字段
0
:不显示1
显示字段
{password:0}
不返回密码字段注意
:值为0的时候尽量都选为0的字段 、混着用容易出错 -
只返回指定字段时
projection 可以使用字符串'username isAdmin'
字段中间空格
//分页查询
router.get('/user/userList', function (req, res, next) {
/*
* limit(Number) ; 限制获取的数据条数
* skip(2) ; 忽略数据的条数
* sort 排序 1:升序 -1 降序
* */
//注意必须是number类型
let {page=1,pageSize=10}=req.query.page;
page = Number(page); //当前页数
pageSize = Number(pageSize); //每页条数
let skip = (page - 1) * pageSize;
//搜索内容
let search={username:'test'}
//countDocuments() 获取总条数
User.countDocuments(search).then(function (count) {
User.find(search,{'password':0}).sort({_id: -1}).limit(pageSize).skip(skip).then(function (list) {
if (list.length) {
responseData.message = 'success';
responseData.userList = list;
responseData.count = count;
res.json(responseData);
return;
}
})
})
})
关联表查询
- 建表结构时增加关联字段
Model.populate()
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
//内容表结构
module.exports = new Schema({
//关联字段- 内容分类的id
category:{
//类型
type:Schema.Types.ObjectId,
//引用
ref:'Category' // `表名`
},
imgPath:String,
//关联字段- 用户id
user:{
//类型
type:Schema.Types.ObjectId,
//引用
ref:'User' // `表名`
},
//简介
views:{
type:Number,
default:0
},
})
//populate('category') //关联一张表时 多个的时候数组传递
//'category', 'user'关联字段
Content.find({}).populate(['category', 'user']).then(function (list) {
})
比较查询运算符
$equals
等于 、 $gt
大于 、$gte
大于等于 、 $lt
小余 、 $lte
小余等于 、 $ne
不等于 、 $in
在数组中 、 $nin
不在数组中
userModel.find({meta.votes: {$lt: 100}});
userModel.find({title: {$in: ['Mongoose', 'Mongodb', 'Nodejs']}});
逻辑查询运算符
$or
或 / $and
与 / $nor
非
userModel.find({ $and: [
{meta.votes: {$gte: 50}},
{meta.votes: {$lt: 100}}
]});
userModel.find({ $nor: [
{meta.votes: 50},
{meta.votes: 100}
]});
上面两个可以写成如下
userModel.and([
{meta.votes: {$gte: 50}},
{meta.votes: {$lt: 100}}
]);
userModel.nor([
{meta.votes: 50},
{meta.votes: 100}
]);
评估查询运算符
$regex
$where
支持js表达式查询
//搜索以“Mongoose”开头的“title”字段,“options”中的“i”代表不区分大小写。
userModel.find({ title: { $regex: "Mongoose.+","$options":"i"}});
blogModel.find({ $where: 'this.comments.length === 10 || this.name.length === 5' });
blogModel.$where(function() { return this.comments.length === 10 || this.name.length === 5; });
//查询“tags”的字段值同时包含有['nodejs', 'mongoose']的数据。只要值中包含此数组即返回数据,若是只包含数组中的一个则不返回此数据。
blogModel.find( tags: ['nodejs', 'mongoose']);
其他常用的运算符
Mode.limit(val)
Mode.skip(val)
Mode.sort(arg)
1、asc为升序,-1、desc为降序
Mode.select(arg)
选择指定字段
//只包含“title”、“body”字段。
userModel.select('title body');
//排除“title”、“body”字段。
userModel.select('-title -body');