一、MongoDB下载和安装
1、下载
https://www.mongodb.com/download-center/community
2、安装
我安装的是8.0版本的
3、启动和停止MongoBD服务
(1)在图形界面上启动或关闭MongoDB服务
MongoBD安装成功后,会在Windows系统上创建了服务。
打开控制面板,选择管理工具,再选择服务打开,找MongoDB服务选项,可以看到服务状态,也可以设置它的启动类型,也可以右键手动启动和停止该服务。
(2)通过命令行启动和关闭MongoDB服务
我的MongoBD服务器名称是MongoDB,不确定名称的可以运行services.msc去看自己的MongoBD服务器名称。
注意是以管理员身份打开终端窗口
net start MongoDB
net stop MongoDB
二、使用MongoDB
1、MongoDB命令行客户端
(1)配置PATH环境变量
在终端使用命令行访问MongoDB数据库,首先要在Windows系统配置PATH环境变量,具体配置步骤为:
先复制好bin目录的路径,打开设置,选择高级系统设置,点击环境变量,找到系统变量里的path,双击编辑,点击新建,把目录路径粘贴上去,最后确定即可。配置好后重新打开终端。
(2)连接MongoDB数据库
连接本地默认端口(27017)且无需认证的数据库
mongosh
出现Connecting to: mongodb://127.0.0.1:27017/… 表明连接成功,并且出现 test> 命令行提示符,意味着已进入 mongosh 交互环境,可以在此输入 MongoDB 操作命令,如创建数据库、插入数据、查询数据等。
连接指定主机和端口的数据库
mongosh --host 主机名 --port 端口号
连接需要身份验证的数据库
mongosh --host 主机名 --port 端口号 -u 用户名 -p 密码 --authenticationDatabase 认证数据库名
(3)操作数据库
use 数据库名
使用该命令,若此数据库存在,就切换到该数据库下,如不存在,则创建出这个数据库。
show dbs
show dbs 是用于显示当前 MongoDB 实例中存在的数据库列表及其占用空间大小的命令。
注意:只有当数据库中至少存在一个集合(Collection )时,该数据库才会在show dbs 的结果中显示 。比如刚创建一个新数据库,还没往里面插入任何集合,使用show dbs 时,这个新数据库不会被列出。
db.student.insertOne({name:“Jack”,sex:“male”,age:25,city:“Shanghai”})
db.student.insertMany([
{name: “Jack”, sex: “male”, age: 25, city: “Shanghai”},
{name: “Alice”, sex: “female”, age: 23, city: “Beijing”}
])
向school数据库中的student集合中插入一条记录,执行后会返回包含插入结果信息的对象
查询 student 集合里的所有文档
db.student.find()
自动添加了id,作为主键字段
此时再执行show dbs,就可以显示school,因为里面有集合了。
2、MongoDB图形客户端
打开MongoDB Compass,新建连接
填写Name,选择Color,按需勾选Favorite this connection,填写完成后,点击Save & Connect 按钮连接 MongoDB 服务器。连接成功后即可看到已创建的数据库,以及该数据的详细数据。
这里的Name,是指当前建立的 MongoDB 连接设置的名称,主要用于方便用户在 MongoDB Compass 中区分和管理多个不同的数据库连接,比如当需要连接本地测试环境的 MongoDB、公司开发环境的 MongoDB 以及生产环境的 MongoDB 时,可以分别为这些连接命名为 “Local Test DB Connection”“Dev Environment Connection”“Production DB Connection” 等,便于快速识别和找到对应的连接。
三、MongoDB用户管理
默认情况下MongoDB是不需要账户就能登录使用的,但是为了数据安全,还是需要设置一个登录的账户。
MongoDB内置了很多种用户角色,创建用户的时候要分配角色。
1、内置角色
以下四个角色的权限仅限于某个逻辑库,不能管理其他逻辑库
1、Read 允许用户读取指定逻辑库
2、readWrite 允许用户读写指定逻辑库
3、dbAdmin 可以管理指定的逻辑库
4、userAdmin 可以管理指定逻辑库的用户
以下四个角色只能创建在admin逻辑库中,可以管理其他逻辑库
1、readAnyDatabase 只能把用户创建在admin逻辑库中,读取任何逻辑库
2、readWriteAnyDatabase 只能把用户创建在admin逻辑库中,读写任何逻辑库
3、dbAdminAnyDatabase 只能把用户创建在admin逻辑库中,允许管理任何逻辑库
4、userAdminAnyDatabase 只能把用户创建在admin逻辑库中,允许管理任何逻辑库用户
以下两种角色必须创建在admin逻辑库,root角色权限最大
1、clusterAdmin 只能把用户创建在admin逻辑库中,允许管理MongoDB集群
2、root 只能把用户创建在admin逻辑库中,超级管理员,拥有最高权限
2、设置登录账户
首先要切换到admin逻辑库,再创建root角色账户
在MongoDB Compass中点击Open MongoDB shell,进入一个类似命令行的交互界面。
use admin
db.createUser({user:"admin",pwd:"abc123456",roles:[{role:"root",db:"admin"}]})
即便创建了用户,MongoDB默认没有开启登录验证功能,开启这个功能操作如下:
1、修改 MongoDB 配置文件
①在安装目录下,例如C:\Program Files*MongoDB\Server\8.0\bin\mongod.cfg* (具体路径可能因安装设置而异)
②打开配置文件,在文件中找到security 部分(如果没有则直接添加),添加以下配置项来启用身份验证:authorization: enabled,保存并关闭配置文件。
2、重启 MongoDB 服务
以管理员身份打开命令提示符,输入net stop MongoDB 停止服务,再输入net start MongoDB 启动服务。或者也可以在“服务”窗口中找到MongoDB服务,右键点击并选择 “重新启动”。
3、使用身份验证连接 MongoDB
重启服务后,MongoDB 已启用登录验证功能。使用以下命令连接(这里以连接到admin 数据库为例):mongosh -u “admin” -p “your_password” --authenticationDatabase “admin”,其中-u 后接用户名,-p 后接密码,–authenticationDatabase 指定进行身份验证的数据库。如果连接成功,就可以继续使用 MongoDB 并创建其他用户、管理数据库等操作。
操作步骤如下图所示:
3、使用认证连接
(1)第一种方式:
可以使用上述的**mongosh -u “admin” -p “your_password” --authenticationDatabase “admin”**方式
(2)第二种方式:
用户隶属于哪个逻辑库,就先切换到该逻辑库,然后再认证连接。
# 1. 连接到MongoDB
mongosh --host localhost --port 27017
# 2. 切换到admin数据库
use admin
# 3. 认证(成功返回1)
db.auth("admin", "abc123456")
# 4. 验证权限(例如查看所有数据库)
show dbs
在db.auth(“admin”, “abc123456”)时,返回“{ ok: 1 }”,表示连接成功。
(3)第三种方式:
在图形化界面上操作,点击新建连接(如果之前连接过了,点击remove关闭连接)后,操作如下所示:
这里的Username,Password,Authentication Database与前面创建的用户角色信息要一致。最后点击Save&Connect即可。
四、MongoDB操作
1、MongoDB的数据结构
MongoDB用BSON(二进制JSON)来保存数据,一条记录就是一个BSON,被称作文档(Document)
某些BSON聚集在一起,就形成了集合(Collection)
2、管理逻辑库
1、创建/切换逻辑库
use 逻辑库
2、查看逻辑库
show dbs
3、删除逻辑库
db.dropDatabase() 当前在哪个逻辑库下,就删了哪个
3、管理集合
1、创建集合
db.createCollection(“student”)
2、查看集合
show collections
3、查看集合记录数量
db.student.countDocuments()
4、查看数据空间容量,单位字节
db.student.dataSize()
5、重命名集合
db.student.renameCollection(“stu”)
4、添加记录
集合的insertOne() 方法允许添加一条记录,insertMany()方法允许添加多条记录
use school
db.student.insertMany([
{
name: "李强",
sex: "男",
birthday: "2012-3-4",
class: "5-2",
city: "北京"
},
{
name: "刘娜",
sex: "女",
birthday: "2014-2-3",
class:"3-6",
city:"上海"
}
])
输出结果:
查看集合的部分
新插入的两条记录的没有age字段,这也说明了nosql数据库为了加快数据库的读写速度,没有太多的约束,在保存数据时不会检验每条记录的字段相同。
5、主键值(ObjectId)以及时间戳
(1)主键值
在集合中,文档之间都是松散的,没有统一的字段约束。为了标识文档的唯一性,MongoDB为每个文档都添加了主键约束(_id)
ObjectId是一个12字节 的BSON类型的字符串
(2)时间戳
MongoDB存储日期会自动转换成格林尼治时间,ObjectId字段里面包含了时间戳,所以可以提取出记录保存的时间,使用ObjectId(“682dfddf907f2ed88906b7f2”)**.getTimestamp()**获取北京时间
6、查询记录
find函数可以从集合中提取记录,参数为查询条件
(1)无条件查询
db.student.find({})可以查询出所有记录
(2)有条件查询
db.student.find({sex:“male”,age:{$gte:20}})表示查询性别为男,且年龄大于等于20岁的记录
db.student**.findOne()**只会返回查到的第一条记录。里面可以有参数,也可以没有参数。
(3)使用正则表达式查找数据
//查询姓李的学生
db.student.find({name:/^李/})
//查询姓名由2-10个字母组成的学生
db.student.find({name:/^[a-zA-Z]{2,10}$/})
(4)分页查找数据
使用skip() 和 **limit()**实现分页查询
skip()函数设置起始位置,而limit()函数设置偏移量
//查询前十条记录
db.student.find({}).limit(10)
//跳过前两条往后取一条记录
db.student.find({}).skip(2).limit(1)
7、数据排序
sort() 函数可以用来对结果集排序,1代表升序,-1代表降序
//按照姓名升序(字符在字符集编号排序)
db.student.find({}).sort({name:1})
db.student.find({}).sort({name:1}).skip(1).limit(2)
8、排除重复
distinct() 函数替代find()函数 查找不重复的记录
//根据city字段去重
db.student.distinct("city") //[ 'Shanghai', '上海', '北京' ]
//根据city字段去重后降序排序
db.student.distinct("city").sort(function(){return -1}) //[ '北京', '上海', 'Shanghai' ]
//根据city字段去重后取前两条记录
db.student.distinct("city").slice(0,2) //[ 'Shanghai', '上海' ]
9、修改记录
(1)updateOne() 和 updateMany() 函数能实现对记录的修改
//修改名为李强的年龄改为26,班级改为2-6
db.student.updateOne({name:"李强"},{$set:{age:26,class:"2-6"}})
//把26岁以上的男同学班级改为2-6
db.student.updateMany({age:{$gte:26},sex:"男"},{$set:{class:"2-6"}})
(2)$ unset和$inc
$ unset:可以删除记录中的字段,$inc:对某个字段值做加法运算
//删除每个学生记录的city和tel属性
db.student.updateMany({},{$unset:{city:1,tel:1}})
//把每个学生记录的age属性都加上2
db.student.updateMany({},{$inc:{age:2}})
(3)$push 和 $pull
$push:可以向数组属性添加元素
$pull:可以删除数组属性的元素
//给jack记录添加教务主任角色
db.teacher.updateMany({name:"Jack"},{$push:{role:"教务主任"}})
//删除jack的副校长角色
db.teacher.updateMany({name:"Jack"},{$pull:{role:"副校长"}})
10、删除记录
remove()函数可以删除记录
//删除所有教师记录
db.teacher.remove({})
//删除2-6班所有的男同学
db.student.remove({class:"2-6",sex:"男"})
11、索引操作
(1)创建索引
因为MongoDB中存放了大量的数据,所以为了加快数据检索速度,需要为集合设置索引。另外,因为创建索引的过程会阻塞MongoDB,影响其他增删改查操作,所以background参数代表在空闲的时候创建索引。
//基于student集合的name字段创建一个升序索引
db.student.createIndex({name:1}) //name_1,MongoDB为该索引命名为name_1
//删除索引
db.student.dropIndex("name_1")
//非阻塞形式创建索引
db.student.createIndex({name:1},{background:true})
//创建索引时定义索引的名字
db.student.createIndex({name:1},{background:true,name:"name"})
//获取索引信息
db.student.getIndexes()
(2)唯一性索引
只能创建在每个记录都含有的公共字段上,在非公共字段上是不能创建唯一性索引的。
//先为每个记录都添加sid字段
db.student.updateOne({name:"Jack"},{$set:{sid:8000}})
db.student.updateOne({name:"刘娜"},{$set:{sid:8001}})
db.student.updateOne({name:"陈浩"},{$set:{sid:8002}})
//为公共字段sid创建唯一性索引
db.student.createIndex({sid:1},{background:true,unique:true,name:"sid"})
(3)创建索引的原则
数据量很大的集合必须创建索引,相反则不需要创建索引
集合的数据读取多过写入,则需要创建索引
给经常被当做查询条件的字段设置索引
12、表达式
MongoDB的表达式必须写成JSON格式
$lt 小于
$gt 大于
$lte 小于等于
$gte 大于等于
$in 包括
$nin 不包括
$ne 不等于
$all 全部
$not 全部
$or 或关系
$exists 含有字段
//查询年龄不在28到30岁之间的记录
db.student.find({age:{$not:{$gte:28,$lte:30}}})
//查询30岁以下的男生或者25岁以下的女生
db.student.find({$or:[{age:{$lt:30},sex:"男"},{age:{$lt:25},sex:"女"}]})
//查询含有age字段的学生
db.student.find({age:{$exists:1}})
五、数据导入与导出
1、导出集合数据
mongoexport命令可以把一个集合的数据导出成JSON或者CSV格式的文件,在使用之前需下载对应版本的 Database Tools,并配置好环境变量
mongoexport --host=localhost --port=27017 -u admin -p abc123456 --authenticationDatabase=admin -d school -c student -o D:/data/student.json
2、导入集合数据
mongoimport --host=localhost --port=27017 -u admin -p abc123456 --authenticationDatabase=admin -d test -c student --file D:/data/student.json
3、导出逻辑库的数据
mongodump命令可以导出逻辑库的数据
- -dumpDbUsersAndRoles参数可以备份隶属于逻辑库的用户
mongodump --host=localhost --port=27017 -u admin -p abc123456 --authenticationDatabase=admin -d school -o D:/
4、导入逻辑库的数据
mongorestore命令可以把导出的数据导入到逻辑库中
mongorestore --host=localhost --port=27017 -u admin -p abc123456 --authenticationDatabase=admin --drop -d school D:/school
六、MongoDB与Python的交互
pymongo是python语言操作MongoDB常用的驱动模块
安装模块:pip install pymongo
1、创建连接
from pymongo import MongoClient
client = MongoClient(
host="localhost",
port=27017,
username="admin",
password="abc123456",
authSource="admin", # 指定认证数据库
authMechanism="SCRAM-SHA-256"
)
# 测试连接
client.admin.command('ping')
2、数据写入
insert_one和insert_many两个函数可以向MongoDB写入数据
from mongo_db import client
client.school.teacher.insert_one({"name":"李璐"})
client.school.teacher.insert_many([
{"name":"陈刚"},
{"name":"郭丽丽"}
])
3、数据查询
find_one和find可以从MongoDB中查询数据
from mongo_db import client
try:
teachers = client.school.teacher.find({})
for one in teachers:
print(one['_id'],one['name'])
print('-'*30)
teacher = client.school.teacher.find_one({'name':'李璐'})
print(teacher['_id'],teacher['name'])
except Exception as e:
print(e)
4、数据修改
update_one和update_many可以修改MongoDB数据
from mongo_db import client
client.school.teacher.update_many({},{'$set':{'role':['班主任']}})
client.school.teacher.update_one({'name':'李璐'},{'$set':{'sex':'女'}})
client.school.teacher.update_one({'name':'李璐'},{'$push':{'role':'年级主任'}})
5、数据删除
delete_one和delete_many
from mongo_db import client
try:
#删除李璐这条记录
client.school.teacher.delete_one({'name':'李璐'})
client.school.teacher.delete_many({})
except Exception as e:
print(e)
6、其他操作
from mongo_db import client
# 分页查询
students = client.school.student.find({}).skip(0).limit(10)
for one in students:
print(one['_id'],one['name'])
# 查询不重复的姓名
names = client.school.student.distinct('name')
for one in names:
print(one)
# 排序
students = client.school.student.find({}).sort([('name',-1)])
for one in students:
print(one['_id'],one['name'])
7、文件存储
(1)GridFS存储引擎
GridFS是MongoDB的文件存储方案,主要用于存储超过16M(BSON文件限制)的文件(如:图片、音频等),对大文件有着更好的性能。
(2)GridFS存储原理
GridFS使用两个集合来存储文件,一个是chunks集合,用来存放文件;另一个集合是files,用来存储文件的元数据。
GridFS会把文件分割成若干chunks(256KB),然后在files记录它们。
(3)连接GridFS
需要创建GridFS对象
(4)保存文件
put函数可以把文件存储到GridFS中
from mongo_db import client
from gridfs import GridFS
db = client.school
gfs = GridFS(db,collection = 'book')
file = open('文件名.pdf','rb')
args = {'type':'PDF','keyword':'Python'}
gfs.put(file,filename = '文件名.pdf',**args)
file.close()
book.chuncks可以看到文件被分成了许多数据包
book.files里存放的文件的描述信息。
(5)在GridFS中查找文件
使用find和find_one函数查询GridFS中存储的文件
from mongo_db import client
from gridfs import GridFS
import math
db = client.school
gfs = GridFS(db,collection = 'book')
book = gfs.find_one({'filename':'文件名.pdf'})
print(book.filename)
print(book.type)
print(book.keyword)
print('%dM' %(math.ceil(book.length/1024/1024))) #文件占用的存储空间大小
print('*'*40)
books = gfs.find({'type':'PDF'})
for one in books:
uploadDate = one.uploadDate + datetime.timedelta(hours = 8)
updateDate = uploadDate.strftime('%Y-%m-%d %H:%M:%S')
print(one._id,one.filename,one.uploadDate)
(6)判断是否存储了文件
exists函数可以判断是否存储某个文件,存在返回True,不存在返回False。
from bson.objectid import ObjectId
rs = gfs.exists(ObjectId('682ee9513dd32f57d208863e'))
print(rs) #True
rs = gfs.exists(**{'filename':'123.html'})
print(rs) #False
(7)读取文件
get函数可以从GirdFS中读取文件,并且只能通过主键查找文件
from mongo_db import client
from gridfs import GridFS
from bson.objectid import ObjectId
db = client.school
gfs = GridFS(db,collection = 'book')
document = gfs.get(ObjectId('682ee9513dd32f57d208863e'))
file = open('D:/data/python.pdf','wb')
file.write(document.read())
file.close()
(8)删除文件
delete函数可以从GridFS中删除文件,并且只能通过主键先查找记录
from mongo_db import client
from gridfs import GridFS
from bson.objectid import ObjectId
db = client.school
gfs = GridFS(db,collection = 'book')
gfs.delete(ObjectId('682ee9513dd32f57d208863e'))