首页 > 数据库 >MongoDB进阶系统学习3——MongoDB高级操作

MongoDB进阶系统学习3——MongoDB高级操作

时间:2023-03-26 22:04:38浏览次数:69  
标签:进阶 MongoDB db 高级 error Expected got id EOF


第三部分:MongoDB高级操作

5 聚合分组统计(管道)

5.1 聚合aggregate

  • 聚合(aggregate)是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,
  • 可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。
  • db.集合名称.aggregate({管道:{表达式}})
  • 先传入数据到stu(学生)集合中
    db.stu.insert({name:“郭靖”, hometown:“蒙古”, age:20, gender:true})
    db.stu.insert({name:“黄蓉”, hometown:“桃花岛”, age:18, gender:false})
    db.stu.insert({name:“华筝”, hometown:“蒙古”, age:18, gender:false})
    db.stu.insert({name:“黄药师”, hometown:“桃花岛”, age:40, gender:true})
    db.stu.insert({name:“段誉”, hometown:“大理”, age:16, gender:true})
    db.stu.insert({name:“段王爷”, hometown:“大理”, age:45, gender:true})
    db.stu.insert({name:“洪七公”, hometown:“华山”, age:18, gender:true})

注意:
MongoDB语句可以现在pycharm中编写,然后复制到CMD窗口中
现在pycharm中使用ctrl+c复制命令,然后CMD窗口点击鼠标右键,就自动粘贴了
可以一次复制多行,有时候会出现粘贴不上去的情况

  • db.集合名称.aggregate({管道:{表达式}})
  • 管道和表达式都可以有多个
  • 管道:
    在mongodb中,⽂档处理完毕后, 通过管道进⾏下⼀次处理
    常用管道如下:
    $group: 将集合中的⽂档分组, 可⽤于统计结果
    $match: 过滤数据, 只输出符合条件的⽂档
    $project: 修改输⼊⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果
    $sort: 将输⼊⽂档排序后输出
    $limit: 限制聚合管道返回的⽂档数
    $skip: 跳过指定数量的⽂档, 并返回余下的⽂档
    $unwind: 将数组类型的字段进⾏拆分
  • 表达式:
    处理输⼊⽂档并输出
    语法:表达式:’$列名’
    常⽤表达式:
    $sum: 计算总和,
    $sum:1 表示以⼀倍计数
    $avg: 计算平均值
    $min: 获取最⼩值
    $max: 获取最⼤值
    $push: 在结果⽂档中插⼊值到⼀个数组中
    $first: 根据资源⽂档的排序获取第⼀个⽂档数据
    $last: 根据资源⽂档的排序获取最后⼀个⽂档数据

5.2 $group分组统计

  • $group注意点
  • $group对应字典中有几个键,结果中对应就有几个值
  • 分组依据必须放在_id的值中
  • 取不同的字段的时候需要使用MongoDB进阶系统学习3——MongoDB高级操作_升序country,$age
  • 取字典嵌套的字典中的值的时候MongoDB进阶系统学习3——MongoDB高级操作_数据_02_id.country
  • 能够同时按照多个组进行分组
  • 管道依次按顺序处理,常用处理顺序过滤-分组-重整

实例

  • 语法格式:
    先写分组,必须使用_id作为键,然后里面的_id代表以哪个字段进行分组
    后面的字段是分组里面进行统计,求和,求平均值,最大值等等
    分组里面的键都是自己指定的,值是集合里面有的字段,前面都需要$符号
  • 统计整个文档
  • _id为null
  • 整个文档求和求平均值
    db.stu.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: …d:null, count:{sum:1}, mean_age:{MongoDB进阶系统学习3——MongoDB高级操作_字段_03age"}}}
    )
  • 指定条件进行分组,然后统计
  • 按性别分组(注意KaTeX parse error: Expected 'EOF', got '}' at position 12: 符号不能遗漏,还要注意}̲不要遗漏) db.stu.ag…group:{_id:"$gender"}}
    )
  • 按性别分组,然后统计每个性别的和,同时求最小值
    db.stu.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"gender", count:{KaTeX parse error: Expected 'EOF', got '}' at position 6: sum:1}̲, min_age:{min:"$age"}}}
    )
  • 按家乡进行分组,统计个数,求平均年龄
    db.stu.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"hometown", count:{KaTeX parse error: Expected 'EOF', got '}' at position 6: sum:1}̲, mean_age:{avg:"$age"}}}
    )

5.3 $project重构

  • 修改文档结构,修改输出的格式
    _id字段的键使用gender进行替换
    _id:0 不显示_id字段
    count:1 显示count字段
    avg_age:1 显示avg_age字段
    db.stu.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"gender", count:{KaTeX parse error: Expected 'EOF', got '}' at position 6: sum:1}̲, avg_age:{avg:“KaTeX parse error: Expected 'EOF', got '}' at position 5: age"}̲}}, {project:{_id:0, gender:”$_id", count:1, avg_age:1}}
    )

5.4 $match过滤

  • 选择年龄大于20的学生,观察男性和女性的人数
    db.stu.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: match:{age:{gt:16}}},
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"gender", count:{KaTeX parse error: Expected 'EOF', got '}' at position 6: sum:1}̲}}, {project:{_id:0, gender:"$_id", count:1}}
    )
  • 选择年龄大于20或者家乡是蒙古或大理的学生,观察男性和女性的人数
    db.stu.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: match:{or:[{age:{KaTeX parse error: Expected 'EOF', got '}' at position 6: gt:16}̲},{hometown:{in:[“蒙古”, “大理”]}}]}},
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"gender", count:{KaTeX parse error: Expected 'EOF', got '}' at position 6: sum:1}̲}}, {project:{_id:0, gender:"$_id", count:1}}
    )
  • 综合练习:
  • 统计出每个country/province下的userid的数量(同一个userid只统计一次)
    db.dv3.insert({“country” : “china”, “province” : “sh”, “userid” : “a” } )
    db.dv3.insert({  “country” : “china”, “province” : “sh”, “userid” : “b” } )
    db.dv3.insert({  “country” : “china”, “province” : “sh”, “userid” : “a” }  )
    db.dv3.insert({  “country” : “china”, “province” : “sh”, “userid” : “c” } )
    db.dv3.insert({  “country” : “uk”, “province” : “bj”, “userid” : “da” } )
    db.dv3.insert({  “country” : “china”, “province” : “bj”, “userid” : “fa” }  )
  • 所有字段进行分组,可以达到去重的效果,上面第一行于第三行数据相同
    db.dv3.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: …{_id:{country:"country", province:“MongoDB进阶系统学习3——MongoDB高级操作_升序_04userid”}}}
    )
  • 上面去重后的结果继续按照国家和省份进行分组,然后统计每个分组的和
  • 第一次分组后第二次分组,第二次分组使用第一次的分组的_id
  • 分组后的结果重整结构
    db.dv3.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: …{_id:{country:"country", province:“MongoDB进阶系统学习3——MongoDB高级操作_升序_04userid”}}},
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: …{_id:{country:"_id.country", province:“KaTeX parse error: Expected 'EOF', got '}' at position 14: _id.province"}̲, count:{sum:1}}},
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: …ject:{country:"_id.country”, province:"$_id.province", count:1, _id:0}}
    )

5.5 sort排序,skip,limit

  • 学生按年龄升序排列
    db.stu.aggregate(
    {$sort:{age:1}}
    )
  • 学生按性别分组,统计个数,然后按个数降序排列
    db.stu.aggregate(
    {KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"gender", count:{KaTeX parse error: Expected 'EOF', got '}' at position 6: sum:1}̲}}, {sort:{count:-1}}
    )
  • skip和limit
  • 先跳过两个,然后选定两个
    db.stu.aggregate({KaTeX parse error: Expected 'EOF', got '}' at position 7: skip:2}̲,{limit:2})

5.6 unwind拆分

  • 将⽂档中的某⼀个数组类型字段拆分成多条, 每条包含数组中的⼀个值
  • 语法:db.集合名称.aggregate({MongoDB进阶系统学习3——MongoDB高级操作_数据_06字段名称’})
    db.t2.insert({_id:1,item:‘t-shirt’,size:[‘S’,‘M’,‘L’]})
    db.t2.aggregate({MongoDB进阶系统学习3——MongoDB高级操作_数据_06size’})
    结果如下:
    { “_id” : 1, “item” : “t-shirt”, “size” : “S” }
    { “_id” : 1, “item” : “t-shirt”, “size” : “M” }
    { “_id” : 1, “item” : “t-shirt”, “size” : “L” }
  • 字段unwind拆分后,统计长度
  • 插入数据
    db.t3.insert({username:“Alex”, tags:[“C+”, “Java”, “Python”]})
  • 拆分tags,统计拆分后的文档个数
    db.t3.aggregate({KaTeX parse error: Expected 'EOF', got '}' at position 24: …sername:"Alex"}}̲, {unwind:"KaTeX parse error: Expected 'EOF', got '}' at position 6: tags"}̲, {group:{_id:null, sum:{$sum:1}}})
  • 先匹配到用户,然后对tags进行拆分,然后按null(不指定字段,所有文档分组)分组,然后统计分组的个数

6 创建索引

  • 先插入数据,使用js语法
    for(i=0;i<10000;i++){db.t12.insert({name:“test”+i,age:i})}
    数据较多,插入较慢,一分钟左右
    查看数据条数
    db.t12.find().count()
  • 查找数据,并查看耗费时间

db.t12.find().count()
100000
db.t12.find({name:“test30000”})
{ “_id” : ObjectId(“5cf8d888e1d09b780e764cd9”), “name” : “test30000”, “age” : 30000 }
db.t12.find({age:30000}).explain(‘executionStats’)
{…
“executionStats” : {
“executionSuccess” : true,
“nReturned” : 1,
“executionTimeMillis” : 82,
“totalKeysExamined” : 0,
“totalDocsExamined” : 100000,

}
上面花费时间82ms

  • 建立索引之后对比:
    语法:db.集合.ensureIndex({要建立索引的字段:1}),1表示升序, -1表示降序
    具体操作:
    db.t12.ensureIndex({name:1})
    {
    “createdCollectionAutomatically” : false,
    “numIndexesBefore” : 1,
    “numIndexesAfter” : 2,
    “ok” : 1
    }
    db.t12.find({name:“test30000”}).explain(‘executionStats’)
    “inputStage” : {
    “stage” : “IXSCAN”,
    “nReturned” : 1,
    “executionTimeMillisEstimate” : 0,
    “works” : 2,
    建立索引后查找时间0ms
  • 查看索引
db.t12.getIndexes()
 [
 {
 “v” : 2,
 “key” : {
 “_id” : 1
 },
 “name” : “id”,
 “ns” : “test.t12”
 },
 {
 “v” : 2,
 “key” : {
 “name” : 1
 },
 “name” : “name_1”,
 “ns” : “test.t12”
 }
 ]

  • 上面结果中有两个字典,key就是创建索引的字段
    数据库默认都会以_id字段创建默认索引,默认也是升序
    “name” : 1 就是我们刚刚给name字段创建的索引,创建索引后查询速度明显变快
  • 删除索引:
    db.t12.dropIndex(‘索引名称’)
    db.t12.dropIndex({name:1})
    { “nIndexesWas” : 2, “ok” : 1 }
    删除之后就只有一个默认索引了
  • 在默认情况下创建的索引均不是唯一索引。
    创建唯一索引(可以对数据进行去重,name字段相同的但是只会创建一个索引,自动排除重复的):
    db.t12.ensureIndex({“name”:1},{“unique”:true})
    创建唯一索引并消除重复:
    db.t12.ensureIndex({“name”:1},{“unique”:true,“dropDups”:true})  
    建立联合索引(什么时候需要联合索引):
    db.t12.ensureIndex({name:1,age:1})
  • 爬虫数据去重
  • 使用数据库建立的关键字段(一个或者多个)的唯一索引进行去重
  • URL地址对应数据不会变的情况,URL地址能够唯一判别一条数据的
  • 使用场景:
    URL地址持久化存储在redis集合中,具体步骤:
    拿到URL地址,判断url是否在redis的url集合中
    存在:说明url已经请求过,不再请求
    不存在:url没请求过,请求,同时存储url到该集合中
  • 布隆过滤器
    位操作,将url地址通过算法转换为对应的位置
  • 根据数据本身进行去重
  • 选择特定的字段,使用加密算法(md5,sha1)将字段进行加密,生成字符串
  • 后续新来一条数据,同样的方法进行加密,如果得到的字符串在redis集合中
  • 说明存在,对数据更新,如果不存在,则直接插入该数据

7 数据库备份与恢复

  • 启动本地的mongodb数据库,不需要使用mongo连接数据库
  • 直接启动后使用备份和恢复命令即可对mongodb数据库中所有的dbs进行备份操作
  • 要想将其他数据恢复早mongodb中,也是在该级操作
  • 数据备份:
    参考教程:http://www.baidu.com/link?url=I_GAWYpj6q4l_P4fmTfwd8CxCokr0sFvaZB7yhXT4vG-9BEx1pyXus1DocoxqogW7jUZ_7XbMunaCTlGDIk2S5gSQid5YE1Kd-WTR_YEvdq
  • 备份的语法:
    mongodump -h dbhost -d dbname -o dbdirectory
    -h: 服务器地址, 也可以指定端⼝号
    -d: 需要备份的数据库名称
    -o: 备份的数据存放位置, 此⽬录中存放着备份出来的数据
    -使用mongo连接数据库,可以看到该数据库的地址和端口号
    C:\WINDOWS\system32>net start mongodb
    请求的服务已经启动。
    请键入 NET HELPMSG 2182 以获得更多的帮助。
    C:\WINDOWS\system32>mongo
    MongoDB shell version v4.0.7
    connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
    Implicit session: session { “id” : UUID(“dd815f12-50ec-499d-a162-b5ee7f3003d5”) }
    MongoDB server version: 4.0.7

exit
bye

  • 备份test数据库到H盘的文件夹中:
    mongodump -h 127.0.0.1:27017 -d test -o H:\mongodb\mongobeifen
    C:\WINDOWS\system32>mongodump -h 127.0.0.1:27017 -d test -o H:\mongodb\mongobeifen
    2019-06-09T13:38:50.248+0800 writing test.t12 to
    2019-06-09T13:38:50.338+0800 writing test.stu to
    2019-06-09T13:38:50.339+0800 writing test.dv3 to
    2019-06-09T13:38:50.339+0800 writing test.test1000 to
    2019-06-09T13:38:50.343+0800 done dumping test.stu (7 documents)
    2019-06-09T13:38:50.344+0800 writing test.t3 to
    2019-06-09T13:38:50.347+0800 done dumping test.dv3 (6 documents)
    2019-06-09T13:38:50.348+0800 done dumping test.test1000 (4 documents)
    2019-06-09T13:38:50.349+0800 done dumping test.t3 (1 document)
    2019-06-09T13:38:50.916+0800 done dumping test.t12 (100000 documents)
  • 数据恢复
    恢复语法:
    mongorestore -h dbhost -d dbname --dir dbdirectory
    -h: 服务器地址
    -d: 需要恢复的数据库实例
    –dir: 备份数据所在位置
    mongorestore -h 127.0.0.1:27017 -d douban --dir H:\mongodb\mongobeifen\douban


标签:进阶,MongoDB,db,高级,error,Expected,got,id,EOF
From: https://blog.51cto.com/u_14990501/6150881

相关文章

  • Maven高级——分模块开发与设计
    分模块开发的意义将原始模块按照功能拆分成若干个子模块,方便模块间的相互调用,接口共享 分模块开发创建Maven工程书写模块代码 注意:分模块开发需要先针对模块......
  • Vue进阶(二十八):浅析 Vue 中 computed 与 method 区别
    一、前言computed区别于method的两个点:computed是属性调用,而methods是函数调用;computed带有缓存功能,而methods不是;下面看一个具体例子:<!--HTML部分--><divid="ap......
  • Servlet进阶开发
    Servlet进阶内容概述Cookie和Session的引入Cookie和Session技术的目的:为了解决http协议是无状态的。http协议无状态的意思是,浏览器发起请求(请求中一般是需要携带数据的),服务......
  • mongoDB3.4 Localhost Exception
    localhostexception简单翻译为“本地主机例外”,主要对于开发者(运维人员)而言,通常使用mongoshell来操作mongodb。本地主机例外允许您启用访问控制,然后在系统中创建第一个用......
  • Vue进阶(二十七):Vuex 之 getters, mapGetters, ...mapGetters详解
    一、前言Vuex提供了state状态统一管理树,开发者可以在vue中用computed计算属性接收这些公共状态以便使用。当然,也可以在接收原值的基础上对这个值做出一些改造,如:computed:{......
  • Java进阶基础知识点(包及final关键字、常量)
    一:包的概述包就是文件夹,用来管理各种不同功能的Java类,方便后期代码维护。包的命名规则:公司域名的反写+包的作用,需要全部英文小写,见名知意。例如;com.51cto.domain.student.......
  • Python爬虫基础——05-高级数据类型
    2.10,数据类型高级2.10.1字符串高级:字符串常见操作包括:获取长度lenlen函数可以获取字符串的长度。查找内容find查找指定内容在字符串中是否存在,如果存在就返回该内容在字符......
  • 2023爬虫学习笔记 -- MongoDB数据库
    一、下载安装mongodb1、下载地址https://www.mongodb.com/try/download/community2、一路下一步安装,路径不要出现空格中文等特殊字符3、设置环境变量将bin目录地址放到path......
  • 循环高级
    目录1.无限循环概念:for格式:while格式:do...while格式:无限循环的注意事项:2.条件控制语句break:continue:3.Random使用步骤:4.逢七过5.平方根6.判断是否为质数7.猜数字小游......
  • 全面了解 Redis 高级特性,实现高性能、高可靠的数据存储和处理
    目录高性能、高可用、高可扩展性的原理持久化RDB持久化AOF持久化持久化的配置RDB配置AOF配置持久化的恢复RDB的恢复AOF的恢复RDB和AOF的选择持久化对性能的影响数据的丢失......