首先,确保mongoDB安装成功:
mongod --version
启动和关闭数据库
启动:
mongod
mongodb 默认使用执行 mongod 命令所处盘符根目录下的 /data/db 作为自己的数据存储目录。
停止:
control + C
连接和退出数据库
连接:
# 该命令默认连接本机的 MongoDB 服务
mongo
退出:
exit
数据库、集合等基本操作:
命令 | 说明 |
---|---|
show dbs | 查看显示所有的数据库 |
db | 查看当前操作的数据库 |
use 数据库名称 | 切换到指定的数据库(如果没有会新建) |
db.xxx.insert({"yyy":"zzz"}) | 往 xxx 集合(表)中插入一条数据(如果集合不存在会新建) |
show collections / show tables | 列出该 db 下面所有的集合 |
db.xxx.drop() | 删除集合 xxx |
db.dropDatabase() | 删除当前数据库 【 执行之前用 db 命令确认一下当前数据库是不是你想删除的这个哦 】 |
数据插入
插入数据有4种方法:insert
、insertOne
、insertMany
、save
。
> db.xxx.insert({"name":"xiaoming"}) #insert可以插入一条数据
> db.xxx.insert([{"name":"xiaoming"},{"name":"test_user"}]) #insert也可以插入多条数据
> db.xxx.insertOne({"name":"xiaoming"}) #insertOne只能插入一条数据
> db.xxx.insertMany([{"name":"xiaoming"}]) #insertMany可以插入一条或多条数据,但是必须以列表(list)的形式组织数据
> db.xxx.save([{"name":"xiaoming"},{"name":"test_user"}]) #如果不指定_id,save的功能与insert一样
> db.xxx.save({"_id":ObjectId("5d07461141623d5db6cd4d43"),"name":"xiaoming"}) #如果指定_id,mongodb就不为该条记录自动生成_id了,只有save可以指定_id,insert、insertOne、insertMany都不可以
数据修改
修改数据有2种方法:update
、save
。
- update 的语法格式:
db.collection.update(
<query>, #update的查询条件,类似sql update语句where后面的部分
<update>, #update的对象和一些更新的操作符等,也可以理解为sql update语句set后面的
{
upsert: <boolean>, #可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入
multi: <boolean>, #可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新
writeConcern: <document> #可选,抛出异常的级别
}
)
- save 方法通过传入的文档来替换已有文档。语法格式如下:
db.collection.save(
<document>, #文档数据
{
writeConcern: <document> #可选,抛出的异常级别
}
)
数据删除
数据删除有三种方法:deleteOne
、deleteMany
、remove
。
- deleteOne 和 deleteMany:
> db.my_col.deleteOne({"name":"xming"}) #删除xming的一条成绩记录
> db.my_col.deleteMany({"name":"xming"}) #删除xming的所有成绩记录
> db.my_col.deleteMany({}) #删除表里面的所有内容
- remove 的语法格式:
db.collection.remove(
<query>, #可选,查询条件
{
justOne: <boolean>, #可选,设置为true或者1,表示只删除一个文档,设置为false,表示删除所有匹配的文档,默认为false
writeConcern: <document> #可选,抛出异常的级别
}
)
?:删除 xming 的所有成绩记录:
> db.col.remove({"name":"xming"})
> db.repairDatabase() #remove方法并不会真正释放空间,需要继续执行 db.repairDatabase() 来回收磁盘空间
> db.runCommand({ repairDatabase: 1 }) #与上一句等效,执行一句即可
数据查询
数据查询的方法有:findOne
和 find
。
二者参数等用法一样,但是 findOne 只返回一条匹配的数据,find 返回全部的匹配数据。
- 条件操作符
操作 | sql查询写法 | mongo查询写法 |
---|---|---|
等于 | select * from my_col where score = 75; | db.my_col.find({“score”: 75}).pretty() |
小于 | select * from my_col where score < 75; | db.my_col.find({“score”: {$lt: 75}}).pretty() |
小于等于 | select * from my_col where score <= 75; | db.my_col.find({“score”: {$lte: 75}}).pretty() |
大于 | select * from my_col where score > 75; | db.my_col.find({“score”: {$gt: 75}}).pretty() |
大于等于 | select * from my_col where score >= 75; | db.my_col.find({“score”: {$gte: 75}}).pretty() |
不等于 | select * from my_col where score != 75; | db.my_col.find({“score”: {$ne: 75}}).pretty() |
.pretty()
能让查询结果以格式化的 json 形式打印出来,便于查看。
- 排序、limit 与 skip
.sort()
:1为升序,-1为降序,默认升序。.limit()
:显示多少条数据。.skip()
:跳过多少条数据。
?:以分数从高到低显示学生的 c++ 课程成绩,只显示第10名到第20名的学生:
> db.my_col.find({"class": "c++"}).sort({"score": -1}).skip(9).limit(11).pretty()
- 复合条件查询 and、or
⭕️ and
:find 方法可以传入多个键值对,每个键值对以 逗号
隔开,即常规 SQL 的 AND 条件。
?:查询 xiaoming 同学的 c++ 课程成绩:
> db.my_col.find({"name": "xiaoming", "class": "c++"}).pretty()
?:查询分数在 75 到 85 分之间的成绩记录:
> db.my_col.find({"score": {$gt: 75, $lt: 85}}).pretty()
⭕️or
:MongoDB OR 条件语句使用了关键字 $or
,语法格式如下:
db.col.find(
{
$or: [
{key1: value1}, {key2:value2}
]
}
).pretty()
?:查询 xiaoming 或 zhangsan 的课程成绩:
> db.my_col.find({$or: [{"name": "xiaoming"}, {"name": "zhangsan"}]}).pretty()
- and + or 复合查询
?:查询 xiaoming 的 c++ 或者 python 课程的成绩:
> db.my_col.find({"name": "xiaoming", $or: [{"class": "c++"}, {"class": "python"}]}).pretty()
- 包含
$in
、不包含$nin
、全部$all
?:查询 xiaoming、zhangsan 和 lisa 的成绩:
> db.my_col.find({"name": {$in: ["xiaoming","zhangsan","lisa"]}}).pretty()
?:查询除了 xiaoming、zhangsan 和 lisa 之外,其他人的成绩:
> db.my_col.find({"name": {$nin: ["xiaoming","zhangsan","lisa"]}}).pretty()
all 类似于 in,不同的地方是,in
只需要满足列表中的一个值即可,而 all
需要满足列表中的全部值。
?:需要找出修了 c++ 和 java 课程的学生:
> db.course.find({"course": {$all: ["c++", "java"]}}).pretty() # 用 all 操作符,表示需要满足 c++ 和 java 两项
- 判断字段是否存在 exists
$exists
?:需要找出没有 tel 字段的学生:
> db.stu_info.find({"tel": {$exists: false}}).pretty() #字段不存在就用false,存在就用true
- 空值处理 null
?:找出 tel 为空值的学生:
> db.stu_info.find({"tel": null}).pretty()
{
"_id" : ObjectId("5d08531641623d5db6cd4d50"),
"name" : "lisa"
}
{
"_id" : ObjectId("5d08542e41623d5db6cd4d51"),
"name" : "tom",
"tel" : null
}
这时候把 tel 字段不存在和 tel 值为 null 的情况都查出来了!如果只想找 tel 值为 null 的情况 ❓
> db.stu_info.find({"tel": {$in:[null], $exists:true}}).pretty()
或者直接:
db.stu_info.find({"tel": null}).pretty()
- 取模运算 mod
$mod
?:查找学生成绩取模 10 等于 0 的数据(即100、90、80…):
> db.my_col.find({"score": {$mod: [10, 0]}}).pretty()
- 正则匹配 regex
$regex
?:查询学生名字以 a 开头的学生成绩:
> db.my_col.find({"name": {$regex: /^a.*/}})
- 获取查询结果条数 count
.count()
?:获取学生成绩记录的条数:
> db.my_col.find().count()
当使用 limit 方法 限制返回的记录数时,默认情况下 count 方法 仍然返回全部记录条数。
如果希望返回限制之后的记录数量 ❓
使用 count(true)
或者 count(非0)
:
> db.my_col.find().count()
4
> db.my_col.find().limit(1).count()
4
> db.my_col.find().limit(1).count(true)
1
- distinct 返回唯一不同的值
?:查询课程成绩表中所有学生的名单:
> db.my_col.distinct("name")
- 聚合 aggregate
在MongoDB中,使用聚合框架可以对集合中的文档进行变换和组合,完成一些复杂的查询操作。
聚合框架通过多个构件来创建一个管道(pipeline),用于对一连串的文档进行处理。这些构件包括但不限于:
操作符 | 意义 |
---|---|
$match | 筛选 |
$project | 投射,选择想要的字段或对字段进行重命名 |
$group | 分组 |
$unwind | 拆分 |
$sort | 排序 |
$limit | 限制查询条数 |
$skip | 跳过一些条数 |
?:当需要使用多个操作符来完成文档的聚合时,我们可以传入一个数组条件,这也是aggregate的常见用法:
> db.my_col.aggregate([
{$match: {"name": "xiaoming"}}, #查找 xiaoming 同学的课程成绩
{$project: {"_id": 0}}, #不需要_id字段
{$sort: {"score": -1, "class": 1}}, #按分数降序排序;同样分数的,按课程名字升序排序
{$skip: 1}, #跳过一条数据
{$limit: 1} #只显示一条数据
])
$match
用于对文档集合进行筛选,之后就可以在筛选得到的文档子集上做聚合。
$match
可以使用所有常规的查询操作符($gt
、$lt
、$in
等)。
通常,在实际使用中应该尽可能将 $match
放在管道的前面位置。这样做有两个好处:一是可以快速将不需要的文档过滤掉,以减少管道的工作量;二是如果在投射和分组之前执行 $match
,查询可以使用索引。
$project
可以从子文档中提取字段,可以重命名字段。
?:查找学生课程成绩,不显示 _id 字段,显示姓名、课程、成绩字段,同时将 name 字段重命名为 student_name:
> db.my_col.aggregate([
{$project: {"_id": 0, "student_name": "$name", "score": 1, "class": 1}}
])
$group
类似于 sql 中的 group by,主要用于数据处理。
?:计算每个学生的总课程成绩:
> db.my_col.aggregate([
{$group: {_id: "$name", total: {$sum: "$score"}}}
])
$sum
可以 替换成操作符 $avg
、$min
、$max
,分别表示求平均成绩、最低成绩、最高成绩。
$unwind
可以将数组中的每一个值拆分为单独的文档。
?:有下面一条记录,记录了一篇博客以及下面的评论:
> db.blog.findOne().pretty()
{
"_id":ObjectId("5359f6f6ec7452081a7873d7"),
"title":"这是一篇博客",
"auth":"xiaoming",
"comments":[
{
"author":"lisa",
"date":ISODate("2019-01-01T17:52:04.148Z"),
"text":"Nice post"
},
{
"author":"tom",
"date":ISODate("2019-01-01T17:52:04.148Z"),
"text":"I agree"
}
]
}
现在要找到 lisa 的评论,可以先使用 $unwind
将每条评论拆分为一个独立的文档,然后再进行 match
查询:
> db.blog.aggregate({"$unwind":"$comments"})
{
"results":
{
"_id":ObjectId("5359f6f6ec7452081a7873d7"),
"title":"这是一篇博客",
"author":"xiaoming",
"comments":{
"author":"lisa",
"date":ISODate("2019-01-01T17:52:04.148Z"),
"text":"Nice post"
}
},
{
"_id":ObjectId("5359f6f6ec7452081a7873d7"),
"title":"这是一篇博客",
"author":"xiaoming",
"comments":{
"author":"tom",
"date":ISODate("2019-01-01T17:52:04.148Z"),
"text":"I agree"
}
}
}
> db.blog.aggregate([
{"$unwind":"$comments"},
{"$match":{"comments.author":"lisa"}}
])
- 索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。
索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。
创建索引 的基本语法如下:.createIndex()
db.collection.createIndex(
{key1: option1, key2: option2}, #key为要创建索引的字段,option为创建索引的方式:1 为升序,-1 为降序,可以对多个字段创建索引,称为复合索引
{
background: <boolean> #可选,建索引过程会阻塞其它数据库操作,background 设置为 true 可指定以后台方式创建索引,默认值为 false
unique: <boolean> #可选,建立的索引是否唯一。指定为true创建唯一索引。默认值为false
name: <string> #可选,索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称
sparse: <boolean> #可选,对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档。默认值为 false
}
)
?:对学生成绩表创建索引:
> db.my_col.createIndex({"score": 1}, {background: true}) #在后台创建
> db.my_col.getIndexes() #查看集合索引
> db.my_col.totalIndexSize() #查看集合索引大小
> db.my_col.dropIndex("索引名称") #删除集合指定索引
> db.my_col.dropIndexes() #删除集合所有索引
可视化工具 —— Robo 3T
- 下载安装地址:https://robomongo.org/download
- Robo 3T 使用教程:https://www.cnblogs.com/tugenhua0707/p/9250673.html