MongoDB基本介绍
Mongodb是C++语言编写基于分布式文件存储的开源数据库,属于NOSQL。
Mongodb是在关系型与非关系型数据之间的产品,是非关系数据库中功能最丰富,最像关系型数据的,它面向文档存储,安装与操作起来比较简单
目前:大数据,内容管理,持续交付,移动应用,社交应用,用户数据管理,数据中心领域都有使用
# 什么是mongodb?
Mongodb是文档数据库,提供好的性能,领先的非关系型数据库,采用BSON存储文档数据。
BSON:是josn类型,的一种二进制形式存储格式简称:Binary JSON
相对于json多了data类型和二进制数组
# 为什么用?
1.解构简单,不需要固定结构
2.没有复杂的链接,没有复杂的外键约束
3.深度查询能力,MongoDB支持动态查询,查询api基于v8引擎
4.容易调试
5.容易扩展
6.不需要转化/映射引用对象到数据库对象
7.使用内部内存作为存储工作区,以便更快的取数据
# 使用场景
1.大数据
2.内容管理系统
3.移动端app
4.数据管理
5.日志处理
6.游戏道具处理
MongoDB相对于RDBMS的优势
例如:
游戏道具
[
{id:1,name:'衣服','防御值':1000},
{id:2,name:'武器','攻击值':500,'攻击距离':50},
{id:3,name:'鞋子','移动速度':50,'颜色':'蓝色'}
]
使用mysql存储,会出现大量的字段为none,冗余,表结构是固定的
优势:
1.无固定结构,面向文档,以json格式文档保存数据,数据结构由键值组成(key:val)。mongodb的文档类似于json对象,字段值可以包含其他文档,数组以及文档数组,当个对象的结构清晰。
2.没有复杂的表连接,不需要维护表与表之间的内在关系
3.查询功能强大,丰富的查询语言,查询与sql一样强大,使用基于文档的查询语言,可以对文档进行动态查询,提供丰富的查询操作和索引支持,也有事务操作,可以更快的更稳定的访问数据(mongodb4.0后才真正支持)文档事务。
4.易于扩展与调优,具备高性能,高可用,可伸缩性等特征
5.应用程序对象与数据库对象天然对应
6.可以分片,对数据存储友好,可以基于内存存储或者硬盘存储
7.任何属性,都可以建立索引,多样索引
术语对比
RDBMS | MongoDB | 补充 |
---|---|---|
库(database) | 库(database) | |
表(Table) | 集合(Collection) | |
行/记录(Row) | 文档(Document) | Document就是json结构的一条记录 |
列/字段(Column/Field) | 字段/键/域(Field) | 属性字段名 |
主键(Promary Key) | 对象ID(Objectid) | _id:Objectdi('sadadasaxzzczsd') 由随机数组成 |
索引(index) | 索引(index) | 也是通过普通索引/唯一索引/主键索引/联合索引区分 |
安装
中文网:
https://www.mongodb.org.cn/ 4.2版本 官方6.0版本
1.win安装
使用win安装傻瓜式安装,关于日志与data都已经配置好了只需要启动就可以
custom->设置安装的路径->去掉installmongodb compass(自带的图形管理故居,取消掉) # 默认安转是没有账户密码的需要自己设置
# 默认4.40版本以上已经配置好配置文件在bin/ mongod.cfg
# cmd启动
mongodb/bin/mongod.exe --config mongod.cfg 启动
在浏览器中 127.0.0.1:27017 查看是否已经启动 # 默认端口是27017
# 加载初始化数据库
C:\mongodb\bin\mongod.exe(服务端) --dbpath c:\data\db(创建的数据文件夹data)
# 在cmd中设置服务
设置服务
C:\mongodb\bin\mongod.exe --config "C:\mongodb\mongod.cfg" --install
需要使用管理员启动的cmd进行使用
启动服务
net start Mongodb
关闭服务
net stop Mongodb
移除服务
C:\mongodb\bin\mongod.exe --remove
# 交互工具mongosh 安装后mongodb 是不带交互shll工具的需要在官网安装交互工具
在mongodb官网下载交互工具压缩包
压缩到文件路径 D:\MongoDB\mongosh-1.6.1-win32-x64\bin 设置环境变量
cmd
mongosh 进行启动
2.linux安装 centos
安装平台依赖
sudo yum install libcurl openssl
安装包
在进行安装.tgz 解压安装,配置log文件夹 data数据库文件夹,设置配置文件即可
base
# win需要下载交互客户端 linux不需要直接mongosh直接直接进去
Current Mongosh Log ID: 63b430321337ccc4ba0017aa # 日志id
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+1.6.1 # 终端链接信息
Using MongoDB: 6.0.3 # 服务端版本
Using Mongosh: 1.6.1 # 客户端版本
For mongosh info see: https://docs.mongodb.com/mongodb-shell/ # 更多的交互终端文档地址
------# 警告 未为数据库启用访问控制。对数据和配置的读写访问不受限制 没有设置密码账户
The server generated these startup warnings when booting
2023-01-03T21:19:32.349+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
------
------# 提示开启监控系统
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).
The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.
To enable free monitoring, run the following command: db.enableFreeMonitoring() # 启动命令
To permanently disable this reminder, run the following command: db.disableFreeMonitoring() # 关闭当前提醒
------
# mongodb的wirecTiger存储引擎 mysql中的innodb存储引擎 相似
# 补充:
mongod 与mongosh区别
mongod: 处理mongodb系统的主要进程,主要负责处理数据请求,管理数据存储,执行后台操作,当运行是意味着运行了启动一个mongodb进程,并在后台运行
mongosh:是一个命令实现客户端链接mongod服务的一个工具,用于链接特定的mongod实例,当我们没有携带参数时,默认链接本地的127.0.0.1:27017和mongod的进程
mongodb的默认端口:27017
基础指令
# 启动关闭开启监控系统
db.enableFreeMonitoring();
启动成功后会给你一个url,直接进行访问就可以查询有关部署的指标(磁盘利用率、CPU、操作统计信息等
{
state: 'enabled',
message: 'To see your monitoring data, navigate to the unique URL below. Anyone you share the URL with will also be able to view this page. You can disable monitoring at any time by running db.disableFreeMonitoring().',
url: 'https://cloud.mongodb.com/freemonitoring/cluster/VANJE4LBVQ2SF4EJYW3KTDGRN63MHXLJ',
userReminder: '',
ok: 1
}
db.disableFreeMonitoring();
# 注意:
mongodb在安转完毕,不需要进行用户权限登录认证,需要切换到admin数据库中添加管理员账户,在开启权限认证,
# 命令
1.退出服务端
.eixt ;
quit();
2.查看交互终端的版本
version()
3.帮助文档
help
4.清屏
cls
常用命令
1.查看当前所以在数据库名(对象)
db
2.查看当前全部的数据库(查看当前mongodb中全部数据库)
show dbs
show databases
'''
下载完成后会给3个数据库
admin 72.00 KiB # 管理员相关数据库
config 108.00 KiB # 配置相关数据库
local 72.00 KiB # 日志相关数据库
'''
# 注意:mongodb存在特性,只有有内容的库才能通过show dbs 查看到,没有内容是查看不到的
3.切换数据库(mysql中切换数据库)
use <db> # 如果切换的数据库不存在会自动创建
4.显示当前数据库全部的集合(mysql中查看全部的数据库表)
show collections
show tables
5.查看系统的环境的配置
show profile
6.查看当前系统用户(当前所在数据库的管理员)
show users
db.system.users.find() 列出mongodb下的全部用户需要先进去 use admin数据库
7.查看用户群组(管理员)
show roles
8.查看全部日志
show logs
[ 'global'(全局日志), 'startupWarnings'(启动日志) ]
show log <type> # 查看指定的日志
9.查看更多的查询结果,相当于下一页的作用
it
10 睡眠函数指令(单位微妙)
sleep(微妙)
11.加载指定的js代码到mongodb shll中来 (mongodb使用的是js的v8引擎)
客户端是可以写一些简单的js代码
load
12 打印数据
print()
13.查看服务状态
db.serverStatus()
win 会出现 BSONError: Invalid UTF-8 string in BSON document
官网说明:https://www.mongodb.com/docs/drivers/node/current/fundamentals/utf8-validation/
出现这个问题:电脑名称是中文
db.serverStatus().host值为乱码
14.列出链接mongodb的链接参数
db.getMongo()
db.serverStatus()参数讲解
# 必要重要几个参数
host: 'wkx666', # 主机名称
version: '6.0.3', # mongodb server 版本号
process: 'D:\\MongoDB\\bin\\mongod.exe',
pid: Long("8716"), # 进程pid
uptime: 2400, # 服务启动的秒数 时间段代表有重启,时间长代表稳定运行
uptimeMillis: Long("2398373"),
uptimeEstimate: Long("2398"), # 内部自己计算的启动时间
localTime: ISODate("2023-01-04T13:17:38.501Z"), # 本地时间
connections: {
current: 4, # 当前的链接数
available: 999996, # 支持最大的链接数是多少(可用)
totalCreated: 9, # 历史创建的链接数
active: 2, # 当前的链接数,链接了多少个客户端
threaded: 4, # 线程数
exhaustIsMaster: 0,
exhaustHello: 0,
awaitingTopologyChanges: 1
},
# 全局锁定信息
globalLock: {
totalTime: Long("2885519000"), # mongodb启动的总时间
currentQueue: { # 当前等待锁的数量 互斥锁,等待队列
total: 0, # 当前全局锁的等待个数
readers: 0, # 读等待数 读写分离
writers: 0 # 写等待数 分配
},
activeClients: { # 当前链接客户端数量
total: 0, # 客户端活跃客户端
readers: 0, # 读有多少个
writers: 0 # 写有多少个
}
},
# 与网络相关
network: {
bytesIn: Long("60199"), # 数据库接收的网络传输字节数
bytesOut: Long("366236"), # 从数据库发送出去的网络传输字节数
numRequests: Long("600"), # mongodb接收道德总请求次数
},
# 计数器操作 原子性操作 优化操作 记录增删的操作数
opcounters: {
insert: Long("0"), # 启动至今插入的数据多少条
query: Long("10"), # 启动至今收到的查询总数
update: Long("7"), # 启动至今更新的操作总数
delete: Long("0"), # 启动至今删除的操作总数
getmore: Long("0"), # 启动至今 getmore 操作总数 数据超载
command: Long("617") # 启动至今向数据库发送的命令总数
},
# 存储引擎
storageEngine: {
# 存储引擎 : MMAPv1和in-Memory
# wiredTiger: 将数据持久化在硬盘中,在mongodb3.2之后开始,称为mongodb的正式默认引擎
# in-Memory: 将数据存储在内存中
# MMAPv1: 将数据持久化在硬盘中,mongodb3.2之前是默认引擎 类似于mysql中的myisam
name: 'wiredTiger', # 默认存储引擎wiredTiger
supportsCommittedReads: true,
oldestRequiredTimestampForCrashRecovery: Timestamp({ t: 0, i: 0 }),
supportsPendingDrops: true,
dropPendingIdents: Long("0"),
supportsSnapshotReadConcern: true,
readOnly: false,
persistent: true,
backupCursorOpen: false
},
wiredTiger 比 MMAPv1要更好,更为强大,wiredTiger的写操作会将写入内存中(缓冲区),并持久化到wal(wtite ahead log 写日志中) (单独的子线程)每60秒或者日志文件达到2g会做一次Checkpoint检查点 将当前数据进行持久化,产生一个新的快照,wiredTiger链接初始化恢复到快照最处状态,根据wal恢复数据,保证存储可靠性
Checkpoint 检查点,将内存中的数据冲刷到磁盘文件中,做标记点
1.表示此前的数据已经持久化到数据文件中,以后的数据变更在内存(缓冲区)和wal日志中
2.是一种数据库redo(重做)和data(数据)文件保持一致的机制
3.并发mongodb独有的,mysql中的innodb也有
# 多文档事务 4.0以后版本的新特性
transactions: {
retriedCommandsCount: Long("0"),
retriedStatementsCount: Long("0"),
transactionsCollectionWriteCount: Long("0"),
currentActive: Long("0"), # 当前活动状态事务
currentInactive: Long("0"),# 当前非活动事务
currentOpen: Long("0"), # 打开的事务有多少个
totalAborted: Long("0"), # 中断事务有多少个
totalCommitted: Long("0"),
totalStarted: Long("0"),
totalPrepared: Long("0"),
totalPreparedThenCommitted: Long("0"),
totalPreparedThenAborted: Long("0"),
currentPrepared: Long("0")
},
# 内存相关
mem: {
bits: 64, # 系统位数
resident: 179, # 物理内存消耗 M单位
virtual: 6711, # 虚拟内存消耗
supported: true # 是否显示额外的内存信息
},
# 内置函数
operatorCounters: {
expressions: {
.... # 全部的内置函数的使用频率
},
....
....
}
数据备份(win 需要自行下载工具)
生成数据
备份与恢复操作的数据格式是bson格式,二进制文件 不需要进入mongo终端
导入导出数据格式是json格式,文档文件格式 不需要进入mongo终端
1.生成数据
// 声明随机数
formatnumber=(start,end)=>{
num=Math.round(Math.random()*(end-start))+start
if(num<10){
return '0'+num
}else{
return num
}
}
// 声明随机标题
rend_title=()=>{
num = Math.round(Math.random()*10)
num1 = Math.round(Math.random()*10)
return[
'万象更新' + num,
"抱头鼠窜" + num,
"鸡鸣狗盗" + num,
"鹤发童颜" + num,
"狗急跳墙" + num,
"盲人摸象" + num,
"画蛇添足" + num,
][num1]
}
// 函数目的生成随机数据
data = ()=>{
for(var i=0;i<20000;i++){
// 对当前数据库的orders集合添加数据,相当于mysql对orders表添加数据
db.orders.insert({ // insertOne
'onumber':('000000000'+i).substr(String(i).length),
'title':rend_title(),
'user_id':i
})
if(i%1000==0){
print('已经添加到1000条',Math.ceil(i/1000))
}
}
}
下载网址:
https://www.mongodb.com/try/download/tools
MongoDB Command Line Database Tools Download
数据备份
1.数据备份 // win需要自行下载 mongodump
mongodump -h dbhost(服务器所在的ip:端口) -d dbname(数据库名称) -o dbdirectory(备份的目录路径)
// 例如:
mongodump -h 127.0.0.1:27017 -d test -o C:\Users\wkx\Desktop
2.删除数据库
use test //进入数据库
db.dropDatabase() // 删除
db.orders.find() // 没有任何数据
3.查看集合
db.orders.find() // orders集合的数据 每次显示20条
it // 下一页查看更多
数据备份恢复
1.数据恢复
// --drop 代表删除存在的dbname的数据
mongorestore -h dbhost(id:端口) -d dbname(恢复的数据名称) --dir dbdirectory(当前的备份文件的路径) --drop
例如:
mongorestore -h 127.0.0.1:27017 -d test --dir C:\Users\wkx\Desktop\test --drop
2.进入数据库查看
use test
3.查看orders是否有20000条数据
db.orders.count() // 已经被弃用
db.orders.countDocuments()
数据导出
1.数据导出
mongoexport -h bdhost(id:端口) -d dbname(数据库名) -c collectionname(集合名称表名) -o file(保存的文件名) --type json/csv(格式默认为json/也可以是csv) -f field(备份的字段列表(id,name,age)不指定导出文档的全不字段 csv格式必须要指定)
例如:
mongoexport -h 127.0.0.1:27017 -d test -c orders -o C:\Users\wkx\Desktop\test_orders.json --type json
数据导入
mongoimport -h bdhost(id:端口) -d dbname(数据库名) -c collectionname(集合名称表名) --file filename(导入文件路径) --type json/csv(导入文件的格式) --headerline(是否忽略首行(不认为是真实数据) csv需要使用) -f field(如果是csv需要指定导入的字段)
例如:
mongoimport -h 127.0.0.1:27017 -d test -c orders --file C:\Users\wkx\Desktop\test_orders.json --type json
用户管理
可以分配不同的用户在不同的用户组中,执行的权限也不同,那么可以对数据库的操作也是不同的
创建用户命令
1.语法
db.createUser('user','pwd',writeConcern(详尽))
如果报错 alreac exists 说明当前创建的用户已经存在
2.详细语法
db.createUser(
'user',
'pwd',
// 任意内容,表示用户身份相关介绍 对用户账户的描述 <必须是json格式>
customData{<any information>,"name":"xxx","age":18},
roles:[ // 角色和权限分配 可以绑定多个角色
{role:"角色名",db:"数据库名"},// 可以填写mongodb内置的角色,例如:<role>
....
]
)
// 创建用户是要注意
1.与redis和mysql不同mongodb的用户以<数据库为单位>来分别建立和管理,每个数据库可以有一个或者多个管理员
2.管理员只能管理自己的数据库,不能直接管理其他数据库,需要在内置数据库admin认证后才可以
3.管理员的权限分为2个部分,分别是角色,权限,通过创建用户时roles属性设置
查看用户的命令
1.查看当前数据库下的用户
show users
2.查看mongodb下的全部用户
use admin // 需要先进去admin数据库 通过system集合进行查询
db.system.users.find()
删除用户命令
1.需要进入admin数据库进行删除
use admin
2.删除
db.system.users.remove({条件}) // 当前命令已经被弃用
db.system.users.deleteOne({条件}) // 建议命令
db.system.users.deleteMany({条件}) // 建议命令
例如: 一般按照用户名进行删除
db.system.users.remove({user:"yingmingapp"})
修改用户密码
1.进去指定的数据库中
use yingmingapp
2.进行对数据库下的某个账户进行修改面
db.changeUserPassword("需要修改账户名称","密码")
例如
db.changeUserPassword("yingmingapp","123")
开启用户认证
// 开启用户认证功能需要修改配置文件,在进行重启才能生效
1.打开配置文件,将安全选项的注释取消,设置开启认证参数
security: // 安全相关
authorization: enabled // 开启认证信息
2.重启mongodb
3.开启命令行mongosh
4.进入需要认证的用户的数据库中
例如: use yingmingapp
5.对数据库进行认证
db.auth('用户名','密码')
例如:
db.auth('yingmingapp','123')
如果认证进行操作就会报错: command count requires authentication
6.认证通过后就可以进行对当前的数据库进行操作
// 补充
如果密码错误账户就会报错: Authentication failed
如果登录后,无权操作除了自己数据库外的数据库报错: not authorized on admin to execute command 无权执行命令
// 注意
开启后用户认证配置后,进行操作数据库获这其他操作,都需要进行db.auth()登录认证,只要有权限,那么就可以操作,没有权限就无法操作。
内置角色讲解
// mongodb安装后默认自带的角色
数据库用户角色: // 普通用户
read, 允许用户读指定数据库
readWrite 允许用户读写指定数据库
数据库管理角色: // 针对与整个数据库层面
dbAdmin, 允许用户在指定数据库中管理函数,如索引创建,删除,查看统计访问system.profile
dbOwner, 该数据库的所有者,具有该数据库的全部权限
userAdmin 允许用户向system.users集合写入,可以找指定数据库创建,删除和管理用户
集群管理角色:
clusterAdmin(超级管理员), 只能在admin数据库可用,赋予用户所有分片和复制集相关函数的管理权限
clusterManager(管理员),
clusterMonitor(供集群管理和监控权限),
hostManager(域名管理员)
备份恢复角色: // 拥有这两个角色才有权备份和恢复
backup,
restore
所有数据库角色: // 只能在admin数据库可用
readAnyDatabase(拥有这个角色代表当前账户拥有全部数据库读的权限), 赋予用户所有的读取权限
readWriteAnyDatabase(拥有当前角色的用户可以对全部数据库进行读写权限), 赋予用户全部数据库的读写权限
userAdminAnyDatabase(可以在所有数据中自由分配管理员身份与创建用户), 赋予用户所有数据库的userAdmin权限
dbAdminAnyDatabase(用户拥有所有数据库的dbadmin权限), 赋予用户所有数据库的dbAdmin权限
超级用户角色: // 只能在admin数据库可用 可以理解为上帝
root, 对所有数据库具有超级权限
// 这些角色间接和直接的通过的超级管理员角色
dbAdmin、dbOwner、userAdmin、dbAdminAnyDatabase、userAdminAnyDatabase
创建角色案例
1.创建当前账户用于管理admin数据库的全部账户权限,不具备其他数据库的操作权限,相当于给mongodb创建一个HR角色
use admin // 需要进入admin数据库
db.createUser({ // 创建
user:"admin",
pwd:"123456",
roles:[
{role:"userAdminAnyDatabase",db:"admin"}
]
})
2.创建一个超级管理员用户
use amdin
db.createUser({
user:"root",
pwd:"123456",
roles:[
{role:"root",db:"admin"}
]
})
3.创建用户自己的数据库角色
账户跟着数据库进行绑定的,所以什么数据库的用户,就必须先到指定的库中授权和验证
往往一个项目分配一个数据库,并且这个数据库分配一个管理员
use yingmingapp // 数据库切换
db.createUser({
user:"yingmingapp",
pwd:"123456",
roles:[
{role:"dbOwner",db:"yingmingapp"}
]
})
数据库操作
特殊点:
如果数据库中没有文档的,那么这个库也就不存在,集合也是(monodb会被收回)。
也就是说,数据库中只有存在数据才行,没有数据那么默认可以理解不存在
数据库(库操作)
1.查询mongodb下的数据库
show databases
show dbs // 只会查询到存在数据的库,不存在数据不显示
2.进入数据库
use databasename // 切换数据库,如果数据库存在切换,不存在创建数据库
3.查看当前所在的数据库
db // db.getName()简写
4.删除库
use dbname // 先切换在删除
db.dropDatabase() // 删除后,还是存在当前删除库中
5.查看库的状态
db.stats()
{
db: 'yingmingapp', // 库名
collections: 0, // 集合(数据表)
views: 0, // 数据库的视图数量(虚拟表)
objects: 0, // 具体的数据 (数据的记录)
avgObjSize: 0, // 平均数据的字节大小
dataSize: 0, // 数据库中的数据总数据
storageSize: 0,// 存储引擎占据文件的大小
indexes: 0, // 数据库中的索引数量
indexSize: 0, // 数据库中索引占据大小
totalSize: 0, // 数据库总数量文件大小
scaleFactor: 1,
fsUsedSize: 0, // 文件系统空间占用大小
fsTotalSize: 0, // 文件系统总占用大小
ok: 1
}
// 备注:
在mongodb中最核心的就是文档,如果一个库或者一个库下的集合中的文档被全部删除,则这个库和这个集合就不存在,会被mongodb回收
集合管理(表操作)
集合有两种:固定集合和动态集(区别数据是否是动态变化的)
一般工作中使用的是动态集,单在mongodb优化后,可以对部分数据转为使用固定集来保存,性能更好,查询速度更快,在mongodb中如果使用动态集,起始不需要专门的创建集合,直接添加文档,mongodb也会自动生成动态集合,固定集需要设置存储文档的上限数量,所以需要提前创建集合
集合基本命令
1.创建集合
db.CreateCollection(
<集合名称>, // 同一数据库中集合名称是唯一的不能重复创建
{
capped:<boolean>, // 当前集合是否是固定集,默认布尔值,固定集指限制数据的大小的集合,当数据达到最大时,就会覆盖原来的文档内容
size:<bytes_size>, // 指固定集的最大字节数,单位字节
max:<collection_size> // 指固定集合中包含文档的最大值,单位字节
}
)
capped : 如果是false 就是动态集,如果是true就是固定集(需要添加size和max参数),默认时false
/*
集合中要注意:
1.如果在创建时db.CreateCollection(val1,val2),不添加第二个参数就是动态集
2.添加文档到不存在的数据库中,会自动创建动态集合
例如:
db.user.insert({'name':'mongodb入门'}) // 自动创建集合user,并且添加一条数据
1.创建固定集
固定集名称queue 固定集大小 10000字节 最大数据 100条
db.createCollection('queue',{capped:true,size:10000,max:100})
2.使用固定集注意:
因为设置size和max属性上线,会出现文档被出列的情况,新增超出部分的数据,也会添加到集合中,但是最早被添加的数据会被删除掉,和队列一样。适用于的场景:日志,历史记录等情况
*/
2.查询数据库下的全部集合(表)
show tables
or
show collections
3.查看集合对象 // 可以通多db.集合名称.键盘TAB查看更过的集合操作用法
db.集合名称
or
db.Collection('集合名称')
4.获取集合状态信息
db.集合名称.stats()
// 状态中拥有数据参数解读
{
ns: 'test.queue', // 表命名空间 指定库.表
size: 208, // 集合的总字节大小
count: 5, // 集合的文档数量
avgObjSize: 41, // 文档的的平均字节数
numOrphanDocs: 0,
storageSize: 20480,
freeStorageSize: 0,
capped: true, // 是否是固定集
max: 5, // 固定集中最大文档数量
maxSize: 100096, // 固定集的最大字节数
type: 'file', // 存储类型为file文件
nindexes: 1, // 当前集合的索引数量 没有设置其他的索引时 默认就一个_id
indexBuilds: [],
totalIndexSize: 20480, // 当前集合的索引占用数量总字节数
totalSize: 40960, // 当前集合的数据总集合数
indexSizes: { _id_: 20480 }, // 当前集合的索引的上线数量
scaleFactor: 1,
ok: 1
}
4.删除数据库下的集合(表)
db.集合名称.drop() // 集合中原有的文档数据就没有了
5.查询数据库下的集合中的全部数据(表)
db.数据库.find() // 返回的是一个查询列表
6.给集合中添加数据
db.集合名称.insertOne({'key':'val','key1':'val1'....})
文档管理(表一行数据操作)
增删改查
mongodb中,文档也被称为 object/document 对应就是存储的json数据内容,对应的就是python中的字典或者列表
mongodb中,文档有各种的自定义字段,每一个字段对应的数据值也存在不同的数据格式,根据不同的数据产生不同的数据类型
字段数据类型有:
ObjectID // 用于存储文档的id,区分文档的唯一字段,mongodb中就是一个对象的返回值 由3部分组成 3个字节时间戳 5个字节客户进程生成的随机数 3个字节的增量计数器 为12字节的长的16进制数组成,保证唯一值
String // 字符串最常用的数据类型 mongodb中字符串必须是utf8
Intger // 整数存储数值,为32,或者64 取决服务器
Double // 双精度类型用于存储浮点型,mongodb没有float浮点性说法
Boolean // 布尔值用于存储布尔值(true/false)
Arrays // 数组列表或者多个值存储到一个键中 []
Tumestamp // 时间戳 用于记录文档何时被修改或者被创建,Date(),Tumestamp(),ISODate(),默认时ISODate()
Object // 用于嵌套文档,相当于子属性是另一个json文档,这种方式可以实现嵌套 []
Null // 空值,相当于python None
Symbol // 与字符串用法相同,用于某些使用特殊符号的语言 可以理解为一种二进制的字符串
Date // 用于以UNIX时间格式存储当前日期和时间
Binary data // 二进制数据,常用于保存文件内容,往往是图片,音频,视频 和数据本身
Code // 用于将javaScript代码存入到文档中
Regular expression // 正则表达式/正则/模式修正符
// 注意
mongodb中提供数据类型,但是mongodb中对文档的添加,不需要预先约束字段的类型,而是一种自动推断的类型,上面的数据类型需要知道即可
添加文档(表中一行数据)
/*
mongodb中 文档的数据结构与json基本一样,所有的存储在集合中的数据在内部存储的格式是bson格式,bson格式类似于json的二进制形式的存储格式 是binary bson的简称
*/
1.方式1
db.集合名称.insert(document) // document 是json的格式的数据
2.方式2
db.集合名称.insertOne(document)
例如:
// 因为mongodb使用的js v8,写法就和js代码是相同的
db.users.insertOne( // 如果users库没有就会直接创建
{ // 会自动推断的类型
"name":'wkx', // String
"age":18, // integer
"sex":true, // boolean
"child":{ //object嵌套到当前文档中
"name":"xiaowang", // string
"age":3 // integer
}
}
)
3.方式3 // 可以添加多条数据
db.集合名称.insertMany(
[document,
document]
)
例如: 赋值变量多条数据添加
data1 = {"name":"xiaohua","age":66}
data2 = {'name':'xiaozhao',"age":77}
db.users.insertMany([data1,data2])
4. 获取一条数据后查询内部字段的类型
使用的是js类型,是可以赋值变量的 查看的类型是js类型
可以通过 typeof 查看 数据中的字段的类型
typeof db.users.findOne().name // 获取1条数据的name类型
// 注意
1.如果文档存在_id主键就是更新数据,否则就是添加数据
删除文档(删除表中的整一条数据)
1.方式1 // 删除1条(假设符合条件的有多个,那么只会删除第一个)
db.集合名称.deleteOne(
filter, // removed的条件表达式 一般写法:{'字段名':{'查询器函数':'值'}} 如果不写条件,默认删除表中的全部文档
)
例如:删除文档中age字段为1
db.users.deleteOne(
{"age":{ $eq:1 }} // $eq是等号的意思 也就是 age=1
)
2.方式2 // 删除多条(按照条件符合几条删除几条)
db.集合名称.deleteMany(
filter, // 表达式 般写法:{'字段名':{'查询器函数':'值'}} 如果不写条件,默认删除表中的全部文档
)
例如:删除文档中age字段为18的
db.users.deleteMany(
{"age":{ $eq:18 }} // $eq是等号的意思 也就是 age=1
)
3.按照文档嵌套对象中的字段进行删除
3.1添加
db.users.insertOne(
{
'name':'www',
'age':18,
'child':{'name':'xiaow','age':10}
}
)
3.2删除(条件按照嵌套关系进行删除)
删除文档中数据child为age字段为10的
db.users.deleteOne(
{
'child.age':{$eq:10} // 按照 嵌套字段.嵌套内部的字段
}
)
// 注意:
mongodb中的条件,不仅仅用于删除数据,同时可以作为更新和查询的过滤条件
查询文档(查询数据)
1.获取1条数据
db.集合名称.findOne(
<query查询器> // 查询条件(删除,修改,查询都需要写条件,条件方式都是相同的)
{ // 查询结果的字段投影,指定查询结果显示的字段列 不设置显示全部字段,格式为json格式
<field>:0, // 隐藏字段显示 例如:'_id':0
<field>:1 // 显示字段显示 例如:'title':1
}
)
// findOne案例例如:
db.users.findOne() // 获取第一条数据
查询内容,不显示child字段其他全部显示
db.users.findOne({},{'child':0}) // {}指没有条件,{'child':0} 指不显示child字段内容
2.获取多条
db.集合名称.find(
<query查询器> // 查询条件(删除,修改,查询都需要写条件,条件方式都是相同的)
{ // 查询结果的字段投影,指定查询结果显示的字段列 不设置显示全部字段,格式为json格式
<field>:0, // 隐藏字段显示 例如:'_id':0
<field>:1 // 显示字段显示 例如:'title':1
}
)
// find案例例如:
db.users.find() // 获取全部的数据
不设置条件,同时不显示_id其他字段全部显示
db.users.find({},{'_id':0})
3.以易读的方式显示数据 只能方法find后面使用 6.0之后默认已经结构化适用于6.0之前的
db.集合.find().pretty()
// 注意:
find(参数1,参数2)
参数1:作为查询的条件,如果不想设置条件请使用 :{}
参数2:设置显示的字段内容json格式{"name":0,"age":1} 0不显示 1显示
设置显示条件
{'name':1} 代表只显示name字段,默认会将_id字段同时显示,所以只显示一个字段请设置{'name':1,"_id":0}
// 字段投影就是设置显示需要显示的字段
条件运算符(查询器)重点
// 运用于 更新数据 查询数据 删除数据的条件使用,因为对于这些操作都需要进行条件进行约束
条件运算符在monogdb中配称为查询器,queryter seeletor
1.比较运算
符号: > < => <= != in not in
等于 $eq {'字段名称':{$eq:'等于的值'}} sql类似于: where name = xx
// 案例:查看users表中name字段为xiao66一行数据
db.users.findOne({'name':{$eq:"xiao66"}}) // 返回查询的第一条数据
db.users.find({'name':{$eq:"xiao66"}}) // 返回name=xiao66全部数据 列表
小于 $lt {'字段名称':{$lt:'小于的值'}} sql类似于: where age < 18
// 案例: 年龄小于18的数据
db.users.find({"age":{$lt:18}})
大于 $gt {'字段名称':{$gt:'大于的值'}} sql类似于: where age > 18
// 案例: 年龄大于18的数据
db.users.find({"age":{$gt:18}})
小于等于 $lte {'字段名称':{$lte:'小于等于的值'}} sql类似于: where age => 18
// 案例: 年龄小于等于77的
db.users.find( { "age":{$lte:77} } )
大于等于 $gte {'字段名称':{$gte:'大于等于的值'}} sql类似于: where age <= 18
// 案例: 年龄大于等于77的
db.users.find( { "age":{$gte:77} } )
不等于 $ne {'字段名称':{$ne:'不等于的值'}} sql类似于: where age != 18
// 案例:年龄不等于77的
db.users.find( { "age":{$ne:77} } )
包含 $in {'字段名称':{$in:['包含的值列表形式']}} sql类似于: where age in [18,20,21]
// 案例:年龄包含 6 7 8 9岁的
db.users.find({"age":{$in:[6,7,8,9]}})
不包含 $nin {'字段名称':{$nin:['不包含的值列表形式']}} sql类似于: where age not in [18,20,21]
// 案例:年龄不包含 6 7 8 9岁的
db.users.find({"age":{$nin:[6,7,8,9]}})
2.逻辑运算符
and not or
与 $and {$and:[{"字段名称":{运算符:"对比的值"}},...]} sql类似于 where age = 18 and name = 666
// 案例: name等于www和age小于18岁 还可以携带多个条件
db.users.find(
{
$and:[
{'name':{$eq:"www"}},{'age':{$lt:18}}
]
}
) // 这里的两个条件 与上面的比较运算符是一样的,and方法列表中的两个条件必须满足
或 $or {$or:[{"字段名称":{运算符:"对比的值"}},....]} sql类似于 where age = 18 or name = 666
// 案例: name等于www 或者 age大于77岁 还可以携带多个条件
db.users.find(
{
$or:[
{'name':{$eq:"www"}},{'age':{$gt:18}}
]
}
) // 这里的两个条件 与上面的比较运算符是一样的,$or方法列表中的两个满足1条即可,条件1不满足,对比条件2
非 $not {'字段名称':{$not:{运算符:"对比的值"}}} sql类似于 where not age = 18
// 案例: age 小于 77岁的
db.users.find(
{
'age':{$not: {$lt:77} }
}
) // 取当前条件的反值
或 与组合使用(语法与上面单个条件时相同的只不过需要进行嵌套)
// 案例 查询age字段=18和{name=www或者name=lll}
db.users.find({
$and:[ // and的内部的两个条件
{'age':{$eq:18}}, // 满足
{$or:[{"name":{$eq:'www'}},{"name":{$eq:"lll"}}]}// 内部是or条件 必须满足两个其中一个即可
]
})
3.其他运算符
查看类型(内部的数据类型) $type {'字段名称':{$type:"类型"}} 场景:字符串与整数混淆的字段 或者其他
// 查看name字段 类型字母都为小写
db.users.find({'name':{$type:"string"}}) // 成功内容
字段是否在文档(表)中 $exists {'字段名称':{$exists:"true or false"}}
// 检查name字段是否存在于文档中
db.users.find({'name':{$exists:true}}) // 成功返回数据 失败返回为空
求余数 $mod {'字段名称':{$mod:[除数,余数]}} 仅针对数字类型字段
// 查看字段age/6后等于0的全部数据有哪些
db.users.find({'age':{$mod:[6,0]}}) // age//6 == 0的全部数据
正则 $regex {'字段名称':{$regex:/正则/}}
// 匹配字段name是w开头的有 js正则 /写正则规则/
db.users.find({ 'name': { $regex: /w.*/ } })
自定义条件查询函数(效率差)
慎用!!! 效率差 因为需要额外调用javascript执行引擎才过滤
1.用法1 逻辑比较复杂的情况下,可以使用更多的javascript进行运算处理,函数的结果为true,进行返回
this 相当于集合的名称
db.集合名称.find({
$where:function(){
return <this.字段><js运算符><条件> // js 的语法
}
})
// 案例 查询age=33 或者 age 小于33 的文档
db.users.find({
$where:function(){
return this.age==33 || this.age < 33
}
})
2.用法2,没有那么负载,取函数的返回值作为条件的值
db.集合名称.find({$where:"<this.字段><$运算符><条件>"})
// 案例 查询age=33 或者 age 小于33 的文档
db.users.find({$where:"this.age==33 || this.age < 33"})
文档排序,限制显示数量,偏移量
1.排序显示 sort
db.集合名称.find().sort({'字段名':1}) // 正序
db.集合名称.find().sort({'字段名':-1}) // 正序
例如:
db.users.find().sort({'age':1}) // 按照年龄正序
db.users.find().sort({'age':-1}) // 按照年龄倒叙
db.users.find().sort({'age':-1,"sex":1,....}) // 多字段排序 按照第一个字段排序,如果第一个重复就按照第二个进行潘旭
2.限制显示 limit
db.集合名称.find().limit(显示多少条件整数)
例如:
db.users.find().limit(1) // 显示查询的第一条
3.偏移量 返回结果的开始位置 skip
db.集合名称.find().sort({'字段':1}).limit(1).skip(返回结果的开始坐标位置整数)
例如:
db.users.find().limit(1).skip(2) // 从全部数据的第2下标开始skip(2)显示第一条数据limit(1)
使用顺序:
find(条件设置).sort(排序设置).limit(数据显示数量).skip(从哪里开始显示)
// 可以通过这方法实现数据的分页设置 修改skip中的参数即可
find(条件设置).sort(排序设置).limit(5).skip(0) // 显示1-5条
find(条件设置).sort(排序设置).limit(5).skip(5) // 显示5-10条
更新文档(修改表中的一条数据)
1.更新一条数据updateOne
db.集合.updateOne(
query, // updata查询集条件 写法:{'字段':{'条件':值}}
update, // update的更新的数据,写法{$set:{'需要修改的字段':'修改的值'}} or {$inc:{'需要修改的字段':'修改的值'}}
{
upsert:boolean, // 可选参数,如果修改的值不存在是否传入 默认false,true插入
multi:boolean, // 可选参数,是否将全部符合条件的数据全部更新,还是只更新一条
witeConcern:document // 可选参数,抛出异常级别
}
)
2.更新多条数据updateMany
db.集合.updateMany(
query, // updata查询集条件 写法:{'字段':{'条件':值}}
update, // update的更新的数据,写法{$set:{'需要修改的字段':'修改的值'}} or {$inc:{'需要修改的字段':'修改的值'}}
{
upsert:boolean, // 可选参数,如果修改的值不存在是否传入 默认false,true插入
multi:boolean, // 可选参数,是否将全部符合条件的数据全部更新,还是只更新一条
witeConcern:document // 可选参数,抛出异常级别
}
)
3.替换一条数据
db.集合名称.replaceOne(
filter, // 原数据,符合条件的数据
replacement, // 替换数据
{
upsert:boolean, // 可选参数,如果修改的值不存在是否传入 默认false,true插入
witeConcern:document, // 可选参数,抛出异常级别
collation:document
}
)
// 案例: 将name=xxx整条数据进行替换
db.users.replaceOne(
{'name':{$eq:'xxx'}}, // 、条件 name=xxx
{'name':'已经替换的数据','age':199,"sex":false} // 新数据
)
注意:使用后无论旧数据多少个属性/字段,都会清空替换为新数据
更新专属运算符
1.$inc 递增递减(查询到的值进行递增递减进行更新)
db.集合名称.updateOne(查询条件,{$inc:{'字段名称':val}}) // 递减{$inc:{'字段名称':-值}} 也就是递增 条件的原值+val
// 案例: 给匹配到年龄的人员添加10岁
db.users.updateOne(
{'name':{$eq:'wkx'}}, // 条件 where name=wkx
{$inc:{'age':10}} // 在原有年龄上添加10 age=age+10
)
2.$set 根据条件匹配到的值进行更新为val,如果不存在添加新的键值对(upsert参数必须设置为true)
db.集合名称.updateOne(查询条件,{$set:{'字段名称':val}}) // 原来的值就会被val换
// 案例: 给匹配到的人员更新性别
db.users.updateOne(
{'name':'wkx'}, // 条件 where name=wkx
{$set:{'sex':false}} // sql语句:update users set set=false
)
3.$unset 移除符合条件的键值对
db.集合名称.updateOne(查询条件,{$unset:{'字段名称':val}})
// 案例: 匹配条件的文档中的键值对给移除
db.users.updateOne (
{'name':{$eq:'wkxx'}}, // 条件 name=wkxx
{$unset:{"sex":false}} // 直接将sex=false这键值对从当前文档中移除
)
注意: {$unset:{键:值}} 设置的键值对键与文档中相同即可,值没有规定必须相同
4.$push 给符合条件的字段进行追加'字段必须是数组类型'单
db.集合名称.updateOne(查询条件,{$push:{'数组字段名称':val}})
// 案例: 根据匹配到的条件 对当前文档中的数组字段添加数据
db.users.updateOne(
{'name':{$eq:"xxx"}}, // 条件为 name = xxx
{$push:{"list":'你真牛'}} // list.append('你真牛')
)
注意:
如果是非数组字段,无法添加,类型不对
如果list字段在文档中不存 就会添加一个字段 <字段形式list:[]> 如果存在就追加
5.$pull 给符合条件的字段进行删除<指定成员>'字段必须是数组类型'单
db.集合名称.updateOne(查询条件,{$pull:{'数组字段名称':val}})
// 案例: 根据匹配的条件,对当前文档中的数组字段删除指定成员
db.users.updateOne(
{'name':{$eq:"xxx"}}, // 条件为 name = xxx
{$pull:{"list":'你真牛'}} // list.remove('你真牛') 将全部为<指定成员>的从当前列表删除(无论是几个)
)
6.$pullAll 给符合条件的字段进行<删除多个指定成员>'字段必须是数组类型'
db.集合名称.updateOne(查询条件,{$pullAll:{'数组字段名称':[val1,val2]}})
// 案例: 根据条件 删除数组中的多个指定的值
db.users.updateOne(
{ 'name': { $eq: "xxx" } }, // 条件为 name = xxx
{ $pullAll: { 'list': [1, 2, 3] } } // 将数组符合条件的全部删除(无论是几个)
)
7.$pop 给符合条件的字段进行<删除最后一个或者第一个成员> '字段必须是数组类型'
db.集合名称.updateOne(查询条件,{$pop:{'数组字段名称':val}}) // val必须是1(最后一个成员)或者-1(第一个成员),
// 案例: 根据条件 删除文档字段数组类型的最后一个成员 与 第一个成员
db.users.updateOne(
{ "name": { $eq: "xxx" } }, // 条件为 name = xxx
{ $pop: { "list": 1 } } // list.pop() 删除最后一个成员
)
db.users.updateOne(
{ "name": { $eq: "xxx" } }, // 条件为 name = xxx
{ $pop: { "list": -1 } } // list.pop(0) 删除第一个成员
)
8.$addToSet 结合 $each 往数组属性中追加多个成员
db.集合.updateOne(查询条件,{$addToSet:{'数组字段名称':{$each:[val1,...]}}})
// 案例: 根据条件 对数组属性添加多个成员
db.users.updateOne(
{'name':'xxx'}, // 条件 name = xxx
{$addToSet:
{'list':
{$each:['多条1','多条22','66882']} // 将['多条1','多条22','66882']追加到list数组中
}
}
)
9.$rename 修改表中的字段名称/属性名
db.集合名称(表名).updateOne(查询条件,{$rename:{'需要修改的字段名称(原)':"新字段名称"}})
// 案例: 修改字段名称
db.users.updateOne(
{'name':'xxx'}, // 条件 name = xxx
{$rename:{'sex':"sex1"}} // 将sex字段名修改为sex1字段名
)
// mongodb中的数组类型,内部可以存在其他的复杂类型 [{},[]]
索引操作
数据库的索引,能够极大的提升数据的查询的效率,缩短查询的耗时,如果没有索引,数据库在查询数据时必然时全盘扫描,并提取符合条件的记录。
mongodb中的索引建立,也是为了提升查询的速度和查询的耗时,如果没有索引,那么也是全部扫描结合中的数据,这种扫描查询的效率是最低的,特别大量数据的集合,查询的速度几十秒或者几分钟,这样用户体验查。
索引可以理解为页码,如果有页码那么找到书中的内容就比较方便,没有页码那么就需要1页的翻找
// 默认有一个_id的索引
索引的注意事项
1.mongodb的索引时存储在运行内存中的 ram 索引必须确保索引的大小不超过内存的显示,如果索引大小超过运行的显示,mongodb会删除一些索引【涉及到mongodb的驱除机制】,导致性能下降
2.查询条件下索引不生效:
2.1 正则表达式以及非符号操作 $nin,$not
2.2 算数表达式 $mod
2.3 $where 自定义查询函数
3.索引会在写入数据(添加 更新 删除) 时进行重现排序 如果项目是写多读少,建议少使用或者不适用索引
4.一个集合中索引数量不能超过64个
5.索引名的长度不能超过128个字符 // 索引的名字一般自动生成
6. 一个符合索引最多可以有31个字段 // 两个索引+在一起
7. mongodb索引统一在system.indexes(内置库中)集合中管理,这个索引只能通过cretateindex 和 dropindexes的操作
那些常作为查询的条件字段,这些字段建议使用索引
查看方法
1.查看当前集合(表)中的索引
db.集合名称(表).getIndexes()
[
{
v: 2, // 版本
key: { _id: 1 }, // 默认排序方式 1 为正序
name: '_id_' // 索引的名字
}
]
2.查看索引的大小
db.orders.totalIndexSize()
// 默认情况下插入文档的情况下默认会生成_id(没有指定文档_id字段) 那么_id字段就是文档的唯一主键,mongodb默认会为集合创建_id为主键索引
索引查询分析
mongodb同时提供了查询方法 explain 用来分析优化查询语句(与mysql一样)
// mysql语法 explain select * from 表 可以分析查询是否命中索引
mongodb中的 explain 中的3个参数
queryPlanner,executionStats,allPlansExecution
默认使用: queryPlanner
开发常用: executionStats
// 1.使用:
db.集合名称.find({查询条件}).explain("executionStats")
案例:
db.orders.find({'title':{$eq:'盲人摸象'}}).explain('executionStats')
输出的内容
{
explainVersion: '1', // 版本
queryPlanner: { // 执行优化器选择出来的查询计划 queryPlanner
namespace: 'test.orders', // 当前文档的所在集合的命名空间
indexFilterSet: false, // 是否使用是索引
parsedQuery: { title: { '$eq': '盲人摸象' } }, // 查询条件
queryHash: '244E9C29',
planCacheKey: '244E9C29', // 查询缓存的key值
maxIndexedOrSolutionsReached: false,
maxIndexedAndSolutionsReached: false,
maxScansToExplodeReached: false,
winningPlan: { // 查询的最佳方案
stage: 'COLLSCAN', // < 扫描类型 从当前参数判断查询语句的方式 >
filter: { title: { '$eq': '盲人摸象' } }, // 过滤条件
direction: 'forward' // 查询方向 forward 升序 backward 降序 创建索引是升序创建还是降序创建
},
rejectedPlans: [] // 拒绝执行计划
},
executionStats: {
executionSuccess: true, // 是否执行成功
nReturned: 0, // 返回的结果数,查到按照条件的结果
executionTimeMillis: 15, // 执行耗时 15毫秒
totalKeysExamined: 0, // 索引扫描次数0 如果命中索引就不是0
totalDocsExamined: 20001, // 扫描文当次数(扫描表中的每一行) 当前库为20001条数据 全表扫描了
}
stage扫描类型:
COLLSCAN 全表扫描 没有命中索引全表扫描
IXSCAN 索引扫描 // 期待出现
FETCH 根据索引检索指定的document(文档,表中的数据) // 期待出现
IDHACK 根据主键_id进行查找 // 期待出现
COUNTSCAN count不适用index进行count时返回
COUNT_SCAN count使用index进行count时返回 // 期待出现
SUBPLA 未使用到索引使用 %or 查询的返回
TEXT 使用全文索引进行查询返回
SORT 使用sort排序单无index时返回 // 组合期待出现 是命中索引的行为
SKIP 使用skip跳过但无index时返回 // 组合期待出现 是命中索引的行为
PROJECTION(LIMIT) 使用limit限定结果但无index时返回 // 组合期待出现 是命中索引的行为
索引创建
1.创建索引
普通索引(单列索引),复合索引(多字段索引),多列索引(数组索引索引),全文索引,哈希索引,地理位置索引,ttl索引(在普通索引上添加过期时间)
全文索引不建议使用:建议使用elasticsearch与sphinx全局索引库
db.集合名.createIndex({
// 单字段:普通索引, sort代表排序1升序-1降序
"字段名字1":<sort:type>, # type值可以为text表示创建全文索引
'字段名称2':<sort:type>, # 多个字段被称为:复合索引
'字段名3':[<值1>,<值2>] # 多字段索引: 多列索引数组索引
},{
background:<boolean>,# 创建索引过程是否阻塞数据库的其他操作,指定以后台方式创建索引默认为false
unique:<boolean>, # 是否建立唯一索引,默认值为false 也叫唯一索引
name:<string>, # 索引名字 不设置索引名称: 默认生成 索引的属性名拼接排序规则
expireAfterSeconds:<integer>, # 设置索引的过期时间,与redis 值过期一样,也叫ttl索引
sparse:<boolean>, # 对文档(表)中的字段数据是否不启用索引,默认为false
})
2.创建普通索引
db.集合名称.createIndex({
'字段名称':<sort> # sort 代表升序规则 1正序 -1 倒叙
})
# 案例: 为name字段创建普通索引
db.users.createIndex({'name':1}) // 为users文档(表)中的name字段创建正序的索引
返回值:name_1
因为没有创建索引的名字,默认会生成索引的名字: name_1
查询结果:
db.users.find({'name':{$eq:'www'}}).explain('executionStats') # stage: 'FETCH' 命中索引
3.创建多字段索引
也就是在创建索引是,多设置几个字段(这几个字段需要组合使用,单个使用无法命中索引)
db.集合名称createIndex({
'字段名':<sort>,
'字段名':<sort>,
})
# 案例: 为name 与 age 创建多字段索引
db.users.createIndex({'name':1,"age":1}) 查询时需要name与age一起用才能有效果
返回值:name_1_age_1 以当前两个字段名+排序规则生成的索引名称
查询结果:
db.users.find({$and:[{'title':{$eq:'盲人摸象4'}},{'onumber':{$eq:'000000023'}}]}).explain("executionStats") # stage: 'IXSCAN' 命中索引
# 注意:
1.多字段索引,是对单字段查询没有效果,只有两个字段同时使用才能命中索引
2.最左匹配原则,与mysql的一样,按照左边的字段(第一个多列字段)为那么就会命中多列索引(mysql联合索引)
因为最左匹配原则是按照顺序,(a,b,c),a ab abc 这三种方式都能命中索引,但是bc是无法命中
4.创建全文索引
# 只能给字符串字段进行创建(文本比较多的),其他的无法创建
db.集合名称.createIndex({
'字段名称':'text' // type 只能是text(固定) 表示创建全文索引
})
# 案例 为name创建全文索引
db.users.createIdex({'name':text})
返回: name_text
全局索引查询语法不同: 需要使用$text 与 $search 查询器使用才能命中
db.users.find($text:{$search:"wwww"}).explain('executionStats') # stage: 'TEXT_MATCH' 命中索引
5.多列索引 数组索引
db.集合名称.createIndex({
'数组字段名称': sort
})
# 案例: 数组索引
db.users.createIndex({
'tags':1
})
返回 : tags_1
# 查询结果
db.users.find({'tags':{$eq:['python']}}).explain('executionStats') # stage: 'FETCH' 命中索引
6.唯一索引(当前字段不允许有重复的存在)
db.集合名称.createIndex({
'字段名称':sotr,},
{unique:true} # 当设置为unique为true是 当前建立唯一索引
)
# 案例:创建唯一索引,防止索引名称重复设置名称
db.orders.createIndex({
onumber:1
},{unique:true,name:'oreders_number_unique_1'})
返回:oreders_number_unique_1
#查询
db.orders.find({'onumber':{$eq:'000000001'}}).explain('executionStats') # stage: 'FETCH' 命中索引
7.ttl索引
1.使用ttl索引,索引的关键字段的值类型必须是date类型,如果不是date类型或者字段不存在,那么不会进行删除
2.数据过期的删除工作是mongodb单独线程在内部直行,默认60秒直行一次(有记录删除),不会立即删除的
db.集合名.createIndex({
'字段名': sotr,
},{'expireAfterSeconds':整数秒})
# 案例:
创建数据
db.tats.insertOne({
'date':new Date('2023-1-12 23:49:00')
})
db.tats.createIndex({
'date': sotr,
},{'expireAfterSeconds':10})
8.重建索引
一般在长期项目运行下,索引创建太久,性能下降的时候进行使用
不能在高峰期进行使用,会出现阻塞,数据越多出现的阻塞可能性越大,避开高峰期使用
db.集合名称.reIndex()
删除索引
mongodb创建的文档(表)中的_id创建的主键索引是删不掉的,只能删除自己创建的
1.删除单个索引
db.集合名称.dropIndex('索引的名字')
2.删除全部索引
db.集合名称.dropIndexes()
配置文件信息
# mongod.conf
# for documentation of all options, see:
# http://docs.mongodb.org/manual/reference/configuration-options/
# Where and how to store data.
storage: // 数据存储的位置
dbPath: D:\MongoDB\data
journal:
enabled: true
# engine: // 使用的存储引擎
# wiredTiger:
# where to write logging data.
systemLog: // 系统日志
destination: file // 以文件方式保存
logAppend: true
path: D:\MongoDB\log\mongod.log // 保存的地址文件
# network interfaces
net: // 网络
port: 27017 // 端口
bindIp: 127.0.0.1 // ip
#processManagement:
#security: // 安全相关
#operationProfiling: // 操作相关配置
#replication: // 复制集
#sharding: // 分片
## Enterprise-Only Options: // 企业版配置选项
#auditLog:
#snmp:
mongodb(python使用)
常用于python中的三个模块
pymongo mongoEngine motor
mysql : pymysql mysqldb aiomysql(基于pymsql的异步实现库)
redis : pyredis redis aioredis(基于pyredis的异步实现库)
mongo : pymongo mongoEngine(基于pymongo的实现的orm库,高仿的django的orm) motor(基于pymongo实现的异步库)
pymongo
mongodb官网:https://www.mongodb.com/docs/drivers/python/
文档地址: https://pymongo.readthedocs.io/en/stable/api/index.html
pymongo: 包中有两个重要的部分: bson(python不识别by json格式,作用就是帮助识别) pymongo(客户端部分,交互mongodb服务端)
# 安装
pip install pymongo
数据库链接
import pymongo
from urllib.parse import quote_plus
1.无密码链接(没有开始用户访问权限机制使用)
mongo = pymongo.MongoClient('mongodb://127.0.0.1:27017')
# mongo 就是mongodb的对象
2.有密码链接(开启用户认证机制)
user = quote_plus('yingmingapp') # 统一的进行转换编码形式
pwd = quote_plus('123456')
database = quote_plus('yingmingapp')
mongo = pymongo.MongoClient(f'mongodb://{user}:{pwd}@127.0.0.1:27017/{database}')
数据库链接顺序
import pymongo
from urllib.parse import quote_plus
# 1.进行mongodb链接并且进行用户的认证 [获取的是一个mongodb的对象] [1.use admin 2.db.auth('root','123456')]
user = quote_plus('root') 统一的进行转换编码形式
pwd = quote_plus('123456')
database = quote_plus('admin')
mongo = pymongo.MongoClient(f'mongodb://{user}:{pwd}@127.0.0.1:27017/{database}')
作用:获取可操作全部的数据库名称 返回列表 (只有admin用户才能获取全部,其他用户只能获取当前自己的)
print(mongo.list_database_names())
作用: 获取可操作全部数据库对象(可迭代的对象) 返回一个数据库列表对象 (只有admin用户才能获取全部,其他用户只能获取当前自己的)
print(mongo.list_databases())
# 2.切换指定数据库 [use orders]
db = mongodb['orders'] # 进入指定的数据库中
print(db.list_collections()) # 列出当前数据库全部集合(表) 返回:可迭代集合对象
print(db.list_collection_names()) # 列出当前库下的全部集合(表)的名称 返回: 列表
# 3.链接到当前数据库下的集合中(表) [db.users]
users_table = db['users'] # 链接指定的表中 获取表对象
# 4.获取当前表中得全部数据 [db.users.count()]
print(users_table.count_docments({}))
注意:
1.先获取的是mongodb的对象 [根据当前认证的信息显示,如果是管理员显示全部的mongodb的数据库,如果是数据库管理员,只显示当前管理员显示的数据库]
2.链接指定的数据库中[获取数据库对象]
3.链接到指定的数据库集合中[根据数据库对象链接到数据库下的某张表中才能进行增删改查操作]
数据库操作(切换数据库,链接表)
import pymongo
from urllib.parse import quote_plus
user = quote_plus('root') 统一的进行转换编码形式
pwd = quote_plus('123456')
database = quote_plus('admin')
mongo = pymongo.MongoClient(f'mongodb://{user}:{pwd}@127.0.0.1:27017/{database}')
mongo.list_database_names() # 查看当前mongodb中得全部数据库名称(根据用户权限大小显示全部还是部分)
# 1. 新建数据库/切换数据库 [就是直接切换操作,就可以直接新建数据库(如果切换的数据库不存在,那么就会新建)][use shop]
db = mongo['shop']
db.list_collection_names() # 获取当前数据库下的全部集合名
db.list_collections() # 获取当前数据库下的全部集合对象
# 2.新建集合/切换集合 (切换到当前数据库下的指定集合操作对象中(表)[db.orders],如果数据库中不存在这个集合(表),那么直接新建)
orders_table =db['orders'] # 获取集合操作对象
orders_table.count_documents({}) # 统计当前集合的全部数据
# 3. 删除集合(表)[db.orders.drop()]
orders_table.drop()
文档(表)操作
增加操作(表中得数据)
import pymongo
from urllib.parse import quote_plus
# 1.链接mongodb
user = quote_plus('root') # 统一的进行转换编码形式
pwd = quote_plus('123456')
database = quote_plus('admin')
mongo = pymongo.MongoClient(f'mongodb://{user}:{pwd}@127.0.0.1:27017/{database}')
# 2.切换数据库/新建数据库
db = mongo['yingmingapp']
# 3.切换集合(表)/新建集合(表)
users_table = db['users']
# 4.添加文档[单条数据]
document = {'name': "小明", 'age': 18, 'sex': True, 'mobile': '13312312314'}
ret = users_table.insert_one(document=document) # insert_one({字典}) 返回的结果(对象):新增的id与状态
print(ret.inserted_id) # 返回新增文档的ID
# 5.添加文档[多条]
document_list = [
{'name': "小绿", 'age': 18, 'sex': True, 'mobile': '13312312314'},
{'name': "小紫", 'age': 18, 'sex': True, 'mobile': '13312312314'},
{'name': "小张", 'age': 18, 'sex': True, 'mobile': '13312312314'},
{'name': "小红", 'age': 18, 'sex': True, 'mobile': '13312312314'}
]
ret = users_table.insert_many(document_list) # insert_many(列表) 返回结果(对象):新增的id列表和状态
print(ret.inserted_ids) # 返回新增文档的id列表
删除操作(表中得数据)
import pymongo
from urllib.parse import quote_plus
# 1.链接mongodb
user = quote_plus('root') # 统一的进行转换编码形式
pwd = quote_plus('123456')
database = quote_plus('admin')
mongo = pymongo.MongoClient(f'mongodb://{user}:{pwd}@127.0.0.1:27017/{database}')
# 2.切换数据库/新建数据库
db = mongo['yingmingapp']
# 3.切换集合(表)/新建集合(表)
users_table = db['users']
# 4.删除文档(表中得数据)[一条]
filter = {'name': "小紫"} # 条件
ret = users_table.delete_one(filter=filter) # delete_one(删除的条件)
print(ret.raw_result) # 获取删除的结果 {'n': 1, 'ok': 1.0}
print(ret.deleted_count) # 获取删除的数量 1
# 5.删除文档(表中得数据)[多条]
filter = {'name': "小红"} # 条件
ret = users_table.delete_many(filter=filter)
print(ret.deleted_count) # 返回符合条件删除的数量
print(ret.raw_result) # 获取删除的结果 {'n': 6, 'ok': 1.0}
# 6.按照运算符进行删除(运算符请看前面关于运算符讲解)操作与终端下一样
filter = {'age': {"$lt": 18}} # 条件年龄小于18岁的
ret = users_table.delete_one(filter=filter) # delete_one(删除的条件)
print(ret.raw_result) # 获取删除的结果 {'n': 1, 'ok': 1.0}
print(ret.deleted_count) # 获取删除的数量 1
更新文档(表中得数据)
import pymongo
from urllib.parse import quote_plus
# 1.链接mongodb
user = quote_plus('root') # 统一的进行转换编码形式
pwd = quote_plus('123456')
database = quote_plus('admin')
mongo = pymongo.MongoClient(f'mongodb://{user}:{pwd}@127.0.0.1:27017/{database}')
# 2.切换数据库/新建数据库
db = mongo['yingmingapp']
# 3.切换集合(表)/新建集合(表)
users_table = db['users']
# 4.更新文档[更新一条,匹配的第一条数据]
filter = {'name': "小明"} # 条件
update = {'$set': {'age': 19}}
ret = users_table.update_one(filter=filter, update=update) # update_one(条件,更新内容)
print(ret.raw_result) # 更新返回内容 {'n': 1, 'nModified': 1, 'ok': 1.0, 'updatedExisting': True}
print(ret.modified_count) # 更新的数量1
# 5.更新数据[多条,全部匹配]
filter = {'name': "小明"}
update = {'$set': {'sex': True}}
ret = users_table.update_many(filter=filter, update=update)
print(ret.raw_result) # 更新返回内容 {'n': 2, 'nModified': 2, 'ok': 1.0, 'updatedExisting': True}
print(ret.modified_count) # 更新的数量 2
# 6.替换文档[将满足条件的进行替换第一条 替换文档不需要指定更新的运算符]
filter = {'name': "小张"}
replace = {'name': "小小张", "age": 13, "sex": True, "mobile": 120110}
ret = users_table.replace_one(filter=filter, replacement=replace) # replace_one(条件,替换内容)
print(ret.modified_count) # 替换的数量
查询文档
import pymongo
from urllib.parse import quote_plus
# 1.链接mongodb
user = quote_plus('root') # 统一的进行转换编码形式
pwd = quote_plus('123456')
database = quote_plus('admin')
mongo = pymongo.MongoClient(f'mongodb://{user}:{pwd}@127.0.0.1:27017/{database}')
# 2.切换数据库/新建数据库
db = mongo['yingmingapp']
# 3.切换集合(表)/新建集合(表)
users_table = db['users']
# 4.查询[获取文档(表)全部的数据]
document_find = users_table.find() # 迭代器 可迭代对象
for i in document_find:
print(i)
# 5.查询[获取文档(表)第一条数据]
document_find_one = users_table.find_one() # 字典
print(document_find_one) # 可以进行字典操作
# 6.查询[投影显示字段,只显示需要的字段]
display_dict = {'_id': 0, "name": 1} # id字段不显示(id字段默认一直显示需要设置0不进行显示),只显示name字段
document_find_one = users_table.find_one({},display_dict)
print(document_find_one)
# 7.查询[按照条件查询多条数据-1]
filter = {'name': "小明"} # 条件
document_find = users_table.find(filter) # 迭代器 可迭代对象
print(document_find) # 可迭代对象
for i in document_find: # 循环获取符合条件的全部数据
print(i)
# 8.查询[按照条件获取多条数据-2]
filter = {'age': {"$lt": 18}} # 条件 age小于18的
document_find = users_table.find(filter) # 迭代器 可迭代对象
print(document_find) # 可迭代对象
for i in document_find: # 循环获取符合条件的全部数据
print(i)
# 9.查询[结果排序sort]
'''
pymongo.ASCENDING 降序 1
pymongo.DESCENDING 升序 -1
sort([('字段',升序还是降序),('字段',升序还是降序)]) 多条件 [元祖1,元祖2] 如果元祖1的排序规则重复 按照元祖2排序规则
sort(('字段',升序还是降序)) 单条件 元祖
'''
filter = {'age': {"$gt": 13}} # 条件 age大于18的
order = [('age', pymongo.DESCENDING), ('name', pymongo.ASCENDING)] # 排序规则
document_find = users_table.find(filter).sort(order) # 跟在查询条件后 sort(排序规则)
print(document_find) # 迭代器
for i in document_find: # 循环获取符合条件的全部数据
print(i)
# 10.查询[限制显示数量limit]
filter = {'age': {"$gt": 13}} # 条件 age大于18的
document_find = users_table.find(filter).limit(2) # 跟在查询条件后 limit(显示的数量)
print(list(document_find))
# 11.查询[偏移量skip]
filter = {'age': {"$gt": 13}} # 条件 age大于18的
document_find = users_table.find(filter).skip(1) # 跟在查询条件后 skip(从那一条开始显示) 从0索引计算开始
print(list(document_find))
# 12.查询[自定义函数]
func = {'$where':"this.age == 18"} # 自定义函数 与终端不同终端需要写js函数,python写字符串
document_find = users_table.find(func)
print(list(document_find), 'end',)
motor异步模块使用
# 文档: https://motor.readthedocs.io/en/stable/
pip install motor # 操作基于pymongo 语法相似
import asyncio
import motor.motor_asyncio
async def get_server_info():
conn_str = "mongodb://127.0.0.1:27017"
client = motor.motor_asyncio.AsyncIOMotorClient(conn_str, serverSelectionTimeoutMS=5000)
try:
print(await client.server_info())
except Exception:
print("Unable to connect to the server.")
loop = asyncio.get_event_loop()
print(loop) # 事件循环对象
loop.run_until_complete(get_server_info())
Mongodb的进阶
有3种集群模式
1.主从(不推荐,安全性能太低)
2.副本集
3.分片集
副本集/分片集使用最多的方案,根据数据量与并发量进行衡量,在gb级别(1tb以下)的基本上副本集的方案可以满足,tb级别(1tb以下)采用分片集,解决单机容量和单机并发,这两种有自己的优势和缺点,比如:分片集分片越多那么性能就会降低
副本集
文档:(https://www.mongodb.com/docs/manual/replication/)
副本集:本质上就是具有一种监控模式的主从,与'redis的哨兵主从类似',一组mongodb复制集,就是一组mongod进程,这进程维护一个数据集合,提供数据冗余,高等级可靠性,这是生产部署的基础,理解为:高级的主从设置(监控,错误选取新主机 与redis哨兵很相似),它可以保障书记在生产部署的冗余和可靠性,通过不同的机器上保存的副本保证数据不会应为单点损坏而丢失,能够应对数据丢失和机器损害带来的风险
副本集组成:
1.一个副本集有多个mongodb的实例组成的集群,由一个主(primary)服务器与多个从备份(secondary)服务器组成
2.主(primary)服务器接受写入操作,主会将全部的写操作更改记录到(oplog)日志中
3.备份(secondary)服务器: 复制'主服务器'中oplog日志,并将应用到自身数据集中,如果主服务器不可用,那么一个合格的副服务器就会被选举为主服务器
4.仲裁(arbiter):负责选举仲裁,当前主服务器不可用,它将从副服务器中选举作为主服务器
复制集的架构: 最少由3台服务器组成
1.三成员复制集 1主2从
2.两成员复制集 1主1从1仲裁
1.不使用仲裁架构
1个主服务 2个从服务
# 过程
1.2个从服务器之间也会存在(心跳检测机制),从服务之间进确定是否存活,从服务与主服务之间也存在心跳检测机制
2.主机宕机,从服务可以经过primary选举后,将其中一个从服务提升为主服务
3.原主机恢复正常使用,将作为从数据库加入到复制集中
# primary选举
复制集通过replsetlinitate(或mongo shell 和rs.initiate()) 进行初始化,初始化后成员开始发起primary选举,获得成员投票支持的服务就时主服务器,那么其他的就是从服务器(选举:服务器总数量-仲裁服务数量/2+1)
如果当存活的数量无法选举出来主服务器时,那么复制集无法提供写的操作,只有读操作 # 选用奇数投票
2.使用仲裁架构
1个主服务
1个从服务(可以主服务宕机在选举中成为主数据库)
1仲裁(在选举中只能投票,不能成为主数据库)它相当于观众一样,就是redis哨兵服务器
-- 主服务与从服务和仲裁之间也是存在心跳检测机制的,确定是否还活着
说明:
由于仲裁服务,没有复制数据,所以在架构中提供一个完整的数据副本,仲裁服务只需要更少的资源,代价是有限的冗余和容错
当主进行宕机,将从数据作为主,主修复后,自动加入现有的复制集中
linux安装mongodb
1.下载
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.27.tgz
2.解压
tar -zxvf https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.27.tgz
3.将解压的文件移动到指定文件加
mv https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.0.27 /usr/local/mongodb
4.创建日志文件加与数据库文件夹
mkdir data data/db data/log
5.对上述创建的文件夹设置权限
sudo chmod 666 data/db data/log/
6.创建配置文件
vim mongodb
设置配置
# 数据库数据存放目录
dbpath=/usr/local/mongodb/data/db
# 日志文件存放目录
logpath=/usr/local/mongodb/data/log/mongodb.log
# 日志追加方式
logappend=true
# 端口
port=27017
# 是否认证
auth=true
# 以守护进程方式在后台运行
fork=true
# 远程连接要指定ip,否则无法连接;0.0.0.0代表不限制ip访问
bind_ip=0.0.0.0
7.配置环境变量(可以不设置)
vim /etc/profile 命令打开系统文件
复制到最后一行
export MONGODB_HOME=/usr/local/mongodb
export PATH=$PATH:$MONGODB_HOME/bin
source /etc/profile 命令重启系统配置
8.开放27017端口
firewall-cmd --zone=public --add-port=27017/tcp --permanent
firewall-cmd --reload # 重启
firewall-cmd --zone=public --list-ports # 验证
9.启动mongodb
bin/mongod --config= mongodb.conf # 设置配置文件
bin/mongod -f /usr/local/mongodb/mongodb.conf
10.测试是否开启
linuxip:27017 # 在浏览器进行访问
11.在linux中进行客户端进行交互
mongo
12.查看mongodb运行
ps aux | grep mongo
13.检查端口是否运行
netstat -lanp | grep 27017
14.关闭mongodb服务
/usr/local/mongodb/bin/mongod -f /usr/local/mongodb/mongodb.conf --shutdown
标签:基本,users,Mongodb,数据库,使用,db,索引,mongodb,name From: https://www.cnblogs.com/wkxz/p/17118232.html