一、介绍
- MongoDB 是一个基于分布式文件存储的数据库。
- 由 C++ 语言编写,是一个开源数据库系统。
- 旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
- MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
- MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。
- MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
- 在高负载的情况下,添加更多的节点,可以保证服务器性能。
- 关系型数据库(mysql)与非关系型数据库(mongodb)的区别:
- 关系型和非关系型两方的优缺点以及特性:
- 关系型数据库:
- 特性:
- 关系型数据库是指采用了关系模型来组织数据的数据库;
- 关系型数据库的最大特点就是事务的一致性
- 简单来说,关系模型指的就是二维表格模型,关系型数据库就是由二维表及其之间的关联组成的数据组织
- 优点:
- 容易理解;
- 使用方便;
- 易于维护;
- 支持SQL,可用于复杂的查询
- 缺点:
- 为了维护一执行需要消耗大量的性能,影响读写
- 固定的表结构
- 高并发读写需求
- 海量数据的高效率读写
- 非关系型数据库:
- 特性:
- 使用键值对存储数据
- 分布式
- 不支持ACID特性
- 非关系型数据库严格上来说,不算是一种数据库,应该是一种数据结构化存储方法的集合
- 优点:
1. 无需经过sql层的解析,读写性能高;
2. 基于键值对,数据没有耦合性,容易扩展;
3. 存储数据的格式,nosql使用key:val的形式,文档的形式,图片形式等等,而关系型数据库则只支持基础类型 - 缺点:
1. 不提供sql支持,学习成本高
2. 无事务处理,附加功能和报表支持也不好
二、下载,安装和连接
- 下载
https://www.mongodb.com/try/download/community
选择对应操作系统和版本的压缩包,下载完成后,解压到自定义的安装目录(记住这个目录路径) - 连接mongoDB数据库
2.1. 在任意盘符下创建新文件夹(data),在新文件夹内,再创建新文件夹(db)
2.2. 在安装目录中进入bin文件夹,打开命令提示符(命令提示符中路径必须为当前bin目录,最好以管理员方式打开命令提示符)
2.3. 在命令提示符中输入:mongod --dbpath d:\data\db
在出现的众多提示中,如果出现:waiting for connections on port 27017。表示连接成功
2.4. 切记:当前命令提示符不要关闭,重新在bin目录下打开一个命令提示符
2.5. 在新打开的命令提示符中输入:mongo。进入mongo操作状态
2.6. 开始mongodb数据库的命令操作 - 注意:以下mongo命令都是在进入mongo操作状态后使用
三、mongoDB的常用指令
在操作数据库之前,可以先查看mongodb数据库提供的帮助文档
命令 说明
help 帮助文档
db.help() 数据库帮助文档
db.test.help() 数据库集合帮助文档
db.test.find().help() 数据库集合查询帮助文档
数据库操作
创建并选择:(有则选,无则建) use dbName
查询 db
查看当前数据库 show dbs
查看所有数据库
注:在查看所有数据库时,不显示空数据库
显示数据库信息
查看数据库的状态信息 db.stats()
查看数据库的链接地址 db.getMongo()
查看数据库的版本信息 db.version()
查看当前数据库名称 db.getName()
删除数据库 -- 慎用 db.dropDatabase()
集合的操作
创建集合 db.createCollection(name, options)
name:集合名,字符
options:可选,为对象,可设置属性有:
capped 布尔 (可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数。
autoIndexId 布尔 (可选)如为 true,自动在_id字段创建索引。默认为 false
size 数值 (可选)为固定集合指定一个最大值,以千字节计(KB)。如果 capped 为 true,也需要指定该字段。
max 数值 (可选)指定固定集合中包含文档的最大数量。
删除集合: db.colName.drop()
查看所有集合: show collections
查看当前集合名称: db.getCollectionNames()
数据的操作
用户信息数据设计:
用户名:userName
密码:pass
年龄:age
籍贯:city
如:罗辑,123456,30,北京
{userName:"罗辑",pass:"123456",age:30,city:"北京"}
增
插入单条:db.colName.insert({})
插入多条:db.colName.insert([{},{},...])
插入单条:db.colName.insertOne({})
插入多条:db.colName.insertMany([{},{},…])
删
根据指定的键值对条件:
删除单条数据:db.colName.deleteOne({key:val})
删除多条数据:db.colName.deleteMany({key:val})
删除所有数据:db.colName.deleteMany({})
改
根据指定的键值对条件:
修改单条数据:db.colName.updateOne({key:val},{$set:{key1:newVal,key2:newVal}})
修改多条数据:db.colName.updateMany({key:val},{$set:{key1:newVal,key2:newVal}})
Num为正自增,为负自减
自增/自减单条数据:db.colName.updateOne({key:val},{$inc:{key1:num}})
自增/自减多条数据:db.colName.updateMany({key:val},{$inc:{key1:num}})
数据的操作----查
基本查询所有数据:db.colName.find()
格式化查询所有数据:db.colName.find().pretty()
指定键值对条件查询:db.colName.find({key:val})
指定条件查询(可以为{}表示所有数据),并限制字段显示db.colName.find({key:val},{userName:1, pass:1})
inclusion模式,指定返回的键,不返回其他键
db.colName.find({key:val},{userName:0, pass:0})
exclusion模式,指定不返回的键,返回其他键
注意:_id默认返回,如果不需要,需主动设置_id:0
分页查询: db.colName.find({key:val}).limit(num).skip(start)
num:表示个数
start:表示起始索引,默认为0
排序查询: db.colName.find({key:val}).sort({key:1})
1升序,-1降序
区间查询: - 价格区间
db.colName.find({ key: {$lt:val1, $gt:val2} })
小于val1,大于val2
db.colName.find({ key: {$lte:val1, $gte:val2} })
小于等于val1,大于等于val2
模糊查询: - 搜索
db.colName.find({ key: /val/})
查询key中包含val的数据
db.colName.find({ key: /^val/})
查询key中包含val且以val开头的数据
或查询: - 用户名或手机号登录
db.colName.find({ $or: [{key1:val1},{key2:val2}] })
查询key1为val1或key2为val2的数据
且查询:db.colName.find({ key1:val1, key2:val2 })
查询key1为val1且key2为val2的数据获取指定字段的数据: - 分类
db.colName.distinct("key")
获取指定字段的所有数据,去重并以数组的形式返回
四、node操作数据库
1. 安装node对mongodb的支持(mongoose)
下载并安装mongoose npm install mongoose -S
2. 连接并选择数据库
1. 引入mongoose模块
const mongoose = require("mongoose");
2. 连接mongodb并选择指定数据库:dbName(数据库名)
mongoose.connect("mongodb://localhost:27017/数据库名");
3. 连接成功 mongoose.connection.on("connected",()=>{ })
连接断开 mongoose.connection.on("disconnected",()=>{ })
连接错误 mongoose.connection.on("error",()=>{ })
4. 连接成功之后,将该模块暴露出来:
module.exports = mongoose
3. 创建集合(users.js)
1. 引入数据库的连接 const mongoose = require("./db.js")
2. 创建集合需要使用的通用对象 const Schema = mongoose.Schema;
3. 说明集合需要使用的字段和类型
为了保证id字段绝对不会重复,此时使用第三方模块:node-uuid
下载:npm i node-uuid
引入:const uuid = require(“node-uuid”);
使用:uuid.v1()
const userSchema = new Schema({
userId:{type:String},
userName:{type:String},
pass:{type:String},
age:{type:Number},
.........
})
4. 创建集合后,将该模块暴露出来 module.exports = mongoose.model("users", userSchema);
4. 插入数据(insert.js)
1. 引入创建集合(在创建集合中,引入了连接数据库) const User = require("./users");
2. 语法:
插入单条数据:User.insertMany({}, (err)=>{})
插入多条数据:User.insertMany([{},{},…], (err)=>{})
注意:数据操作,属于异步操作,需要在回调函数中查看插入结果
5. 插入数据(update.js)
1. 引入创建集合(在创建集合中,引入了连接数据库) const User = require("./users");
2. 语法:
修改一条:User.updateOne({key: val}, {$set: {kay: val}}, (err)=>{})
修改一条(自增/自减):User.updateOne({key: val}, {$inc: {kay: val}}, (err)=>{})
修改多条:User.updateMany({key: val}, {$set: {kay: val}}, (err)=>{})
修改多条(自增/自减):User.updateMany({key: val}, {$inc: {kay: val}}, (err)=>{})
6. 删除数据(del.js)
1. 引入创建集合(在创建集合中,引入了连接数据库) const User = require("./users");
2. 语法:
删除一条:User.deleteOne({key: val}, (err)=>{})
删除多条:User.deleteMany({key: val}, (err)=>{})
删除全部:User.deleteMany({}, (err)=>{})
7. 查询数据(find.js)
1. 引入创建集合(在创建集合中,引入了连接数据库) const User = require("./users");
2. 语法:
查找全部:
User.find({},{},(err, data)=>{})
参数1:对象,为查询条件
参数2:对象,要返回的字段
参数3:函数,查询结束后执行
err:报错信息
data:查询到的数据
一种类似于回调函数的方法:exec
User.find({},{}).exec((err, data)=>{})
区间查找:
User.find({key: {$lte:maxVal, $gte:minVal}},{}).exec((err, data)=>{})
模糊查找:
User.find({key: /^张/},{}).exec((err, data)=>{})
查找数据总数量:
User.countDocuments().exec((err, data)=>{})
查找指定字段的数据: - 分类
user.distinct("字段名").exec((err, data)=>{})
8. 封装(sql.js)
封装数据的增删改查
注意异步的处理
利用回调函数处理异步
利用Promise处理异步
module.exports = {
addData(collectName, data){
return new Promise((resolve, reject)=>{
collectName.insertMany(data,(err)=>{
if(!err){
resolve()
}else{
reject(err);
}
})
})
},
delData(collectName, where, num=1){
let type = num === 1 ? "deleteOne" : "deleteMany";
return new Promise((resolve, reject)=>{
collectName[type](where, (err)=>{
if(!err){
resolve()
}else{
reject(err);
}
})
})
},
setData(collectName, where, what, num=1){
let type = num === 1 ? "updateOne" : "updateMany";
return new Promise((resolve, reject)=>{
collectName[type](where, what, (err)=>{
if(!err){
resolve()
}else{
reject(err);
}
})
})
},
getData(collectName, where={}){
return new Promise((resolve, reject)=>{
collectName.find(where, {_id:0,__v:0}).exec((err, data)=>{
if(err){
reject(err)
}else{
resolve(data);
}
})
})
},
getSortData(collectName, s, where={}){
return new Promise((resolve, reject)=>{
collectName.find(where, {_id:0,__v:0}).sort(s).exec((err, data)=>{
if(err){
reject(err)
}else{
resolve(data);
}
})
})
},
getPageData(collectName, num, index, where={}){
return new Promise((resolve, reject)=>{
collectName.find(where, {_id:0,__v:0}).limit(num).skip(num*index).exec((err, data)=>{
if(err){
reject(err)
}else{
resolve(data);
}
})
})
},
getDataLen(collectName){
return new Promise((resolve, reject)=>{
collectName.countDocuments().exec((err, data)=>{
if(err){
reject(err)
}else{
resolve(data);
}
})
})
},
getKind(collectName, col){
return new Promise((resolve, reject)=>{
collectName.distinct(col, (err, data)=>{
if(err){
reject(err)
}else{
resolve(data);
}
})
})
},
}