Advertisement

MongoDB相关知识点梳理

阅读量:

目录

  • 一、MongoDB入门

  • 二、MongoDB基本使用

    • 1.数据增加
    • 2.数据查询
    • 3.数据更新
    • 4.数据删除
    • 5.游标
  • 三、MongoDB索引

  • 四、MongoDB聚合

  • 五、MongoDB深入操作

    • 1.固定集合操作
    • 2.GridFS
    • 3.用户管理

一、MongoDB入门

MongoDB是一种NoSQL数据库,它与关系型数据库的关系如下:

关系型数据库 MongoDB
集合
文档
列(字段) 成员
主键 objectID(MongoDB自动生成,为时间戳+机器码+PID+计数器,不会重复)

相对于传统的关系型数据库,表结构一旦定义,就必须按照结构进行存储;但是MongoDB不同,它可以随意扩充数据,并且没有模式,结构为JSON
MongoDB的安装过程如下:
(1)拉取镜像:

复制代码
    docker pull mongo:latest

(2)创建文件夹:

复制代码
    mkdir /data/mongodb

(3)启动容器(无授权):

复制代码
    docker run --restart=always --name mongo -v /data/mongodb:/data/db -p 27017:27017 -d 镜像ID

至此,MongoDB就安装完成。

二、MongoDB基本使用

1.数据增加

语法:db.集合.insert({"成员1":"内容1","成员2":"内容2"...})
【注】MongoDB无需先创建集合,可以直接向某集合插入数据,如果此集合不存在,会自动创建。

2.数据查询

(1)关系查询:
语法:db.集合.find({"成员":{"操作符":内容}});
包含以下一些操作:
< 1>大于:$gt
< 2>小于:$lt
< 3>大于等于:$gte
< 4>小于等于:$lte
< 5>不等于:$ne
< 6>等于:$eq
【例】查询年龄大于19岁的学生:

复制代码
    db.students.find({"age":{"$gt":19}});

(2)逻辑运算:
语法:db.集合.find("操作符":[{"操作符":{"成员1":"内容1"}},{"成员2":"内容2"}]);
包含以下一些操作:
< 1>与:$and
< 2>或:$or
< 3>非:$not或者$nor
【例】查询年龄大于19岁或者成绩大于90分的学生:

复制代码
    db.students.find({"$or":[{"age":{"$gt":19}},{"score":{"$gt":90}}]});

(3)求模运算:
语法:db.集合.find({"成员":{"$mod":[求模的数字,求模的余数]}});
【例】查询对20岁求模,余数为0的学生:

复制代码
    db.students.find({"age":{"$mod":[20,0]}});

(4)范围查询:
语法:db.集合.find({"成员":{"操作符":[内容1,内容2...]}});
包含以下一些操作:
< 1>在范围中:$in
< 2>不在范围中:$nin
【例】查询年龄在19到20岁的学生:

复制代码
    db.students.find({"age":{"$in":[19,20]}});

(5)数组查询:
语法:db.集合.find({"成员":{"操作符":{条件}}});
包含以下一些操作:
< 1>所有:$all
< 2>规定数组大小:$size
< 3>切割数组:$slice
< 4>元素相等:$elemMatch
【例1】查询所有课程中包含“语文”和“数学”的学生:

复制代码
    db.students.find({"course":{"$all":["语文","数学"]}});

【例2】查询课程数组中第二个内容(即下标为1)是“数学”的学生:

复制代码
    db.students.find({"course.1":"数学"});

【例3】查询只参加2门课程的学生:

复制代码
    db.students.find({"course":{"$size":2}});

【例4】查询年龄为19岁,但只显示参加2门课程的学生:

复制代码
    db.students.find({"age":19},{"course":{"$slice":2}});//$slice的2表示数组前2个;-2表示数组后两个

(6)嵌套集合:
语法:db.集合.find({"成员":{"$elemMatch":{"成员":"内容"}}});
【注】嵌套集合即一个集合中又嵌套了另一个集合(如学生信息中含有父母的信息,尽量不要这么用),只能用$elemMatch查询。
【例】查询父母工作为“局长”的学生:

复制代码
    db.students.find({"parents":{"$elemMatch":{"job":"局长"}}});

(7)字段判断(字段是否存在):
语法:db.集合.find({"成员":{"$exists":true或者false}});
$exists存在以下两种可能:
< 1>存在:true
< 2>不存在:false
【例】查询“父母”字段存在的学生:

复制代码
    db.students.find({"parents":{"$exists":true}});

(8)条件查询:
语法:db.集合.find({"$where":{条件}});
【注】$where只会查出符合条件的一行信息。
【例】查询大于20岁的学生:

复制代码
    db.students.find({"$where":"this.age>20"});

(9)正则查询:
语法:db.集合.find({"成员":{"$regex":"正则标记","$options":"选项"}});
包含以下一些操作:
< 1>忽略大小写:i
< 2>多行查找:m
< 3>空白字符除了被转义或在字符类以外的完全被忽略:x
< 4>匹配所有字符(圆点),包括换行内容:s
【例】查询姓名以“谷”开头的学生:

复制代码
    db.students.find({"name":/谷/});

(10)排序查询:
语法:db.集合.find({条件}).sort({"成员":1或者-1});
$排序存在以下两种可能:
< 1>升序:1
< 2>降序:-1
【例】查询按成绩降序排序的学生:

复制代码
    db.students.find().sort({"score":-1});

(11)分页查询:
语法:db.集合.find({条件}).skip(跳过的数据条数).limit(每页最多展示的条数);
【例】分页查询学生(第1页,每页5条):

复制代码
    db.students.find().skip(0).limit(5);

3.数据更新

MongoDB为数据更新操作提供了两个函数:update()和save();但是一般使用update()。
语法:db.集合.update({更新条件},{"修改器":{"成员":"内容"}},upsert,multi);
语法中后两个表示(不写默认为true):
< 1>upsert:表示若更新数据不存在,则新增一条(true增加,false不增加)
< 2>multi:表示是否只更新满足条件的第一条(true全更新,false只更新第一个)
修改器有如下几种:
(1)$inc:针对于增加某字段数据内容
【例】将年龄为19岁的学生分数减少30分:

复制代码
    db.students.update({"age":19},{"$inc":{"score":-30}},true,true);

(2)$set:重新设置
【例】将年龄为19岁的学生成绩更新为100:

复制代码
    db.students.update({"age":19},{"$set":{"score":100}},true,true);

(3)$unSet:删除某个成员(字段)
【例】将年龄为19岁的学生的分数字段删除:

复制代码
    db.students.update({"age":19},{"$unSet":{"score":1}},true,true);

(4)$push:将内容追加到指定成员之中(此成员值是数组)
【例】将年龄为19岁的学生的课程加一门体育:

复制代码
    db.students.update({"age":19},{"$push":{"course":"体育"}},true,true);

(5)$pushAll:与上一条类似,追加多个内容到数组中
【例】将年龄为19岁的学生的课程加美术和音乐的课程:

复制代码
    db.students.update({"age":19},{"$pushAll":{"course":["美术","音乐"]},true,true);

(6)$addToSet:向数组中增加一个内容,只有当数组中不存在此内容时才增加成功
【例】将年龄为19岁的学生的课程加舞蹈的课程:

复制代码
    db.students.update({"age":19},{"$addToSet":{"course":"美术"},true,true);

(7)$pop:删除数组内数据(1:删除数组第一个;-1:删除数组最后一个)
【例】将年龄为19岁的学生参加的第一个课程删除:

复制代码
    db.students.update({"age":19},{"$pop":{"course":1},true,true);

(8)$pull:从数组内删除指定内容的数据(需要和输入的内容相同才会删除)
【例】将年龄为19岁的学生参加的体育课程删除:

复制代码
    db.students.update({"age":19},{"$pull":{"course":"体育"},true,true);

(9)$pullAll:与上一条类似,一次性删除数组多个内容
【例】将年龄为19岁的学生参加的美术和音乐课程删除:

复制代码
    db.students.update({"age":19},{"$pullAll":{"course":["美术","音乐"]},true,true);

(10)$rename:重命名成员名
【例】将年龄为19岁的学生的“course”成员名改为“课程”:

复制代码
    db.students.update({"age":19},{"$rename":{"course":"课程"},true,true);

【注】在更新MongoDB时我们也可以用先删除再插入的方式更新。

4.数据删除

语法:db.集合.remove({条件},选项)
包含以下2个选项:
< 1>条件:需要被删除数据的条件
< 2>选项:true或者1为只删除一个;默认不写为全部删除
【例】删除名字中带有“谷”的学生:

复制代码
    db.students.remove({"name":/谷/});

5.游标

有了游标,我们就可以把数据进行一行一行的进行操作。用法如下:

复制代码
    var cursor = db.students.find();//已经拿到了游标
    while(cursor.hasNext()){//当还有下一个游标时一直循环拿出
    	var	doc = cursor.next();//取出当前数据
    	printJson(doc);//返回Json格式的数据
    }

三、MongoDB索引

数据库中的索引可以帮助我们更快的查询到数据,在MongoDB中有2种建立索引的方式:自动和手动。
查看现有索引的语法为:db.集合.getIndexs();
为某个成员创建索引的语法为:db.集合.ensureIndex({"成员":1或者-1},{索引类型});
删除单个索引的语法为:db.集合.dropIndex({索引});
删除全部索引(_id索引不会被删除)的语法为:db.集合.dropIndexs();
分析索引使用情况的语法为:db.集合.find({条件}).explain();
强制使用索引的语法为:db.集合.find({条件}).hint({索引});
【注】在没有设置索引名称时,默认为“成员名_索引排序模式
索引有如下几种:
(1)唯一索引:unique
【例】为姓名建立一个唯一索引:

复制代码
    db.students.ensureIndex({"name":1},{"unique":true});

【注】如果在唯一索引的成员上再插入重复的值会报错。
(2)过期索引(类似于缓存有过期时间):expireAfterSeconds
【例】建立一个过期索引(10秒有效期):

复制代码
    db.students.ensureIndex({"createTime":1},{"expireAfterSeconds":10});

【注意】创建过期索引的那个成员必须 是“数据创建时的时间信息”,否则过期索引失效。
【注意】过期索引的过期时间并不一定准确
(3)全文索引:text
【例】1)为课程和班级建立一个全文索引:

复制代码
    db.students.ensureIndex({"course":"text"},{"class":"text"});

2)用全文索引查询课程有“体育或美术”的学生,并且给相关度进行打分(分数越大越准确 ):

复制代码
    db.students.find({"$text":{"$search":"体育 美术"}},{"score":{"$meta":"textScore"}});

(4)地理信息索引:2D(平面)和2DSphere(球面)
查询地理信息有以下2个方式:
< 1>查询最近的点:$near(可再加上maxDistance指定最近的多少个点)
< 2>查询某个形状内的点:$geoWithin
可用的形状如下:
1 >矩形范围(box):**`{"box":[[x1,y1],[x2,y2]]} **2 >圆形范围($center):**{"center":[[x1,y1],半径长度]}` **3 >多边形范围(polygon):{"$polygon":[[x1,y1],[x2,y2],[x3,y3]...]}
【例】1)建立一个地理信息索引:

复制代码
    db.shops.ensureIndex({"location":2d});

【注意】创建地理信息索引的那个成员必须 是“存放坐标信息的成员”,否则地理信息索引失效。
2)查询离当前点(坐标[11,11])最近的5个点:

复制代码
    db.shops.find({"location":{"$near":[11,11],"maxDistance":5}});

3)查询在圆形(圆心[11,11],半径为2)范围内的点:

复制代码
    db.shops.find({"location":{"$geoWithin":{"$center":[[11,11],2]}}});

四、MongoDB聚合

MongoDB产生的背景是大数据,对于大量数据就必须有统计操作,而这样的统计就叫做“聚合”。
不用聚合框架,聚合有如下几个操作:
(1)取得集合个数;
【例】取得学生集合的个数:

复制代码
    db.students.count();

(2)消除重复数据;
【例】消除学生集合中姓名(name)重复的数据:

复制代码
    db.runCommand({"distinct":"students","key":"name"});

使用聚合框架可以帮助我们更便利的聚合,有如下一些操作:
(1)分组:$group
**在group操作中还可做一些计算:** **< 1>平均值:**`avg **< 2>求和:**sum` **< 3>求最大值:**`max **< 4>求最小值:**min` **< 5>放入一个数组:**`push **< 6>数组第一个:**first` **< 7>数组第二个:**`last **< 8>去重再放入数组:**$addToSet`
【例】统计每个职位雇员的人数:

复制代码
    db.emps.aggregate([{"$group":{
    						"_id":"$job",//_id相当于别名;而$job指取得job成员的值
    						"job_count":{"$sum":1}//job_count相当于别名;而$sum是对数据进行的操作,上述例子表示计数器的功能
    						}
    					}]);

(2)投影:$project
project可用于控制成员的显示规则,有一些如下规则:** **< 1>普通列(1显示,0不显示):**`{"成员":1或true}` **< 2>_id列(1显示,0不显示):**`{"_id":1或true}` **< 3>条件过滤的列(满足条件就显示):**`{"成员":条件表达式}` **project还支持如下一些运算:
< 1>四则运算:$add(加)、$subtract(减)、$multiply(乘)、$divide(除)
< 2>关系运算(返回布尔类型):$cmp(比大小)、$eq(等于)、$gte(大于等于)、$lte(小于等于)、$ne(不等于)、$ifNull(判空)
< 3>逻辑运算:$and(与)、$or(或)、$not(非)
< 4>字符串操作:$concat(连接)、$substr(截取)、$toLower(小写)、$toUpper(大写)
【例】只显示name、工资列(其他普通列没写也不显示 )并且不显示_id列,找出工资大于等于2000的雇员:

复制代码
    db.emps.aggregate([{"$project":{
    						"_id":0,//不显示_id列
    						"name":1,//显示name成员
    						"工资":"$salary",//前面的是别名“工资”;后面的是存在MongoDB中的salary成员的值
    						"salary"://别名
    							{"$gte":["$salary":2000]}//salary成员的值大于等于2000进行比较,并返回布尔值
    						}
    					}]);

(3)排序(1升序,-1降序):$sort
【例】显示name列,不显示_id列,按工资降序显示:

复制代码
    db.emps.aggregate([{"$project":{"_id":0,"name":1}},
    				   {"$sort":{"salary":-1}}
    				  ]);

(4)分页:$skip(跳过几条数据)、$limit(每页最多显示几条)
【例】显示name列,不显示_id列,分页(第1页,每页3条)显示:

复制代码
    db.emps.aggregate([{"$project":{"_id":0,"name":1}},
    				   {"$skip":0},//先skip
    				   {"$limit":3}//再limit
    				  ]);

(5)数组转换为字符串(不常用):$unwind
(6)附加的点(见之前的说明):$geoNear
(7)将查询结果输入到指定集合(相当于表的复制):$out
【例】显示name列,不显示_id列,结果输入到emp_infos集合中:

复制代码
    db.emps.aggregate([{"$project":{"_id":0,"name":1}},
    				   {"$out":"emp_infos"}
    				  ]);

【注】以上所有的聚合框架的操作都可以放在一起用,以达到统计聚合的目的!

五、MongoDB深入操作

1.固定集合操作

在MongoDB中,直接向集合中插入数据;若集合不存在,则会自动生成集合。但是MongoDB也可以主动创建一个固定大小的集合。如果固定集合满了,再插入数据,则会根据LRU算法 去除已存在的数据,而保存新的数据(类似于Redis缓存中的内存淘汰)。
语法示例及解释如下:

复制代码
    db.createCollection("集合名称",
    					{"capped":true,//表示创建固定集合
    					 "size":数字,//表示集合占空间的大小(单位为字节)
    					 "max":数字//表示集合中最多存在几条记录
    					});

2.GridFS

MongoDB还支持各种二进制文件的存储(如图片、音乐等),但是需要用户自己处理,用mongofiles命令完成。
步骤如下:
(1)进入文件所在目录;
(2)将文件保存到GridFS中:mongofiles --port=端口 文件名称
(3)查看保存的文件:mongofiles --port=端口 list
(4)在MongoDB中有一个fs系统集合,此集合默认保存在了test数据库下 ;查看保存信息:首先执行use test;,再执行db.fs.files.find();
(5)删除文件:mongofiles --port=端口 delete 文件名

3.用户管理

MongoDB默认可以不用“用户名/密码”而进行直接连接。如果要使用“用户名/密码”,则需要:
(1)MongoDB启动时打开授权认证;
(2)配置“用户名/密码”。
【注意】“用户名/密码”是针对某一个数据库的,所以要先切换到一个数据库上。
创建用户步骤如下:
(1)切换到数据库:use 数据库名
(2)创建用户(任何用户都要有2种角色:read和readWrite ):

复制代码
    db.createUser({
    				"user":"testuser",//设置用户名
    				"pwd":"testpassword",//设置密码
    				"roles":[//设置角色
    						 {
    						  "role":"readWrite",//设置读写角色
    						  "db":"emps"//指定数据库
    						 }
    						]
    			  });

(3)创建后,若想让此用户名生效,则必须以授权方式 打开MongoDB服务;修改MongoDB的启动文件:auth=true
(4)登陆数据库时使用“用户名/密码”:mongo 地址:端口/数据库 -u 用户名 -p 密码
(5)修改密码(要先关闭授权再登陆):db.changeUserPassword("用户名","新密码");

全部评论 (0)

还没有任何评论哟~