Mongodb

一、mongodb的介绍

mongodb的优势

  • 易扩展:NoSQL数据库种类繁多,但是一个共同的特定就是去掉关系数据库的关系型特性。数据之间无关系,这样非常容易扩展
  • 大数据,高性能:NoSQL数据库都具有非常高的读写性能,尤其在大数据量下,同样表现优秀,这得益于它的无关系型,数据库的结构简单
  • 灵活的数据模型:NoSQL无需事先为要存储的数据建立字段。随时可以存储自定义的数据格式,而在关系数据库里。增删字段是一件非常麻烦的事,如果是非常大数据量的表,增加字段简直就是一个噩梦

二、mongodb安装

  • 下载安装包并上传到服务器上
  • 解压安装包
  • 移动到/usr/local/目录下
  • 将可执行文件添加到PATH路径中
# 添加环境变量
vim .bashrc
export PATH=/usr/local/mongodb/bin:$PATH
# 使环境变量生效
source .bashrc
  • mongodb的相关启动,停止,重启,端口查看
# 启动
systemctl start mangodb
# 停止
systemctl stop mangodb
# 重启
systemctl restart mangodb
# 查看是否启动成功
ps -aux |grep mangodb
# 默认端口
27017

三、mongodb基本操作

关于database的基础命令

# 查看当前的数据库:
db
# 查看所有的数据库:
show dbs /show databases
# 切换数据库:
use db_name
# 删除当前的数据库:
db.dropDatabase()

关于集合的基础命令

# 不手动创建集合:
向不存在的集合中第一次加入数据时,集合会被创建出来
# 手动创建集合:
db.createCollection(name,options)
db.createCollection("stu")
db.createCollection("sub",{capped:true,size:10})
参数capped:默认值为false表示不设置上限,值为true表示设置上限
参数size:当capped值为true时,需要指定此参数,表示上限大小,当文档达到上限时,会将之前的数据覆盖,单位为字节。
# 查看集合:
show collections
# 删除集合:
db.集合名称.drop()

数据类型

Object ID:文档ID
string: 字符串,最常用,必须是有效的UTF-8
Boolean:存储一个布尔值,true或false
Integer:整数可以是32位或者64位,这取决于服务器
Double:存储浮点值
Arrays:数组或列表,多个值存储到一个键
Object:用于嵌入式的文档,即一个值为一个文档
Null:存储Null值
Timestamp:时间戳,表示从1970-1-1到现在的总秒数
Date:存储当前日期或时间的UNIX时间格式

注意点

  • 创建日期语句如下:参数的格式为YYY-MM-DD

    new Date('2020-1-1')

  • 每个文档都有一个属性,为id,保证每个文档的唯一性

  • 可以自己去设置 _id 插入文档,如果没有提供,那么Mangodb为每个文档提供了一个独特 _id,类型为objectID

  • objectID是一个12字符的十六进制数:

    • 前4个字节为当前时间戳
    • 接下来3个字节的机器ID
    • 接下来的2个字节中MongoDB的服务进程id
    • 最后3个字节是简单的增量值

插入

  • db.集合名称.insert(document)

    • db.stu.insert({name:'gj',gender:1})
    • db.stu.insert({_id:"20200101",name:'gj',gender:1})
  • 插入文档时,如果不指定 _id参数,MongoDB会为文档分配一个唯一的Objectid

四、mongodb数据查询

mongodb插入数据

  • db.collecion.insert({}) 插入数据,_id存在就报错
  • db.collection.save({}) 插入数据,_id存在会更新

mongodb的更新操作

  • db.test1000.update({name:"xiaowang"},{name:"xiaozhao"})
  • 把name为xiaowang的数据替换为{name:"xiaozhao"}
  • db.test1000.update({name:"xiaohong"},{$set:{name:"xiaozhang"}})
  • 把name为xiaowang的数据name的值更新为xiaozhang
  • db.test1000.update({name:"xiaozhang"},{$set:{name:"xiaohong"}},{multi:true})
  • {multi:true}达到更新多条的目的

mongodb删除

  • db.test1000.remove({name:"xiaohong"},{justOne:true})
  • 默认情况会删除所有满足条件的数据,{justOne:true}能达到只删除一条的效果

mongodb的count方法

  • db.collection.find({条件}).count()
  • db.collection.count({})

mongodb的投影

  • 投影:选择返回结果的字段
  • db.collection.find({条件},{name:1,_id:0})
    • 1._id默认会显示,置为0不显示
    • 2.出了_id之外的其他字段,如果不显示,不写,不能写为0

$group的注意点

  • $group对应的字典中有几个键,结果中就有几个键
  • 分组依据需要放到_id后面
  • 取不同的字段的值需要使用$,$gender,$age
  • 取字典嵌套的字典中的值的时候$_id.country
  • 能够同时按照多个键进行分组{$group:{_id:{country:"$country",province:"$province"}}}
    • 结果是:{_id:{country:"",province:""}

编辑器写mongodb语句

db.stu.find(
{$or:[{age:{$gte:20}},{hometown:{$in:["桃花岛","华⼭"]}}]}
) #按照gender进行分组,获取不同组数据的个数和平均年龄
db.stu.aggregate(
{$group:{_id:"$gender",count:{$sum:1},avg_age:{$avg:"$age"}}},
{$project:{gender:"$_id",count:1,avg_age:"$avg_age",_id:0}}
)
# 按照hometown进行分组,获取不同组的平均年龄
db.stu.aggregate(
{$group:{_id:"$hometown",mean_age:{$avg:"$age"}}}
)
#使用$group统计整个文档
db.stu.aggregate(
{$group:{_id:null,count:{$sum:1},mean_age:{$avg:"$age"}}}
)
#选择年龄大于20的学生,观察男性和女性有多少人
db.stu.aggregate(
{$match:{$or:[{age:{$gt:20}},{hometown:{$in:["蒙古","⼤理"]}}]}},
{$group:{_id:"$gender",count:{$sum:1}}},
{$project:{_id:0,gender:"$_id",count:1}}
) #page37页练习
db.tv3.aggregate(
{$group:{_id:{country:"$country",province:"$province",userid:"$userid"}}},
{$group:{_id:{country:"$_id.country",province:"$_id.province"},count:{$sum:1}}},
{$project:{country:"$_id.country",province:"$_id.province",count:1,_id:0}}
)

数据查询

  • 方法find():查询

    • db.集合名称.find({条件文档})
  • 方法findOne():查询,只返回第一个
    • db.集合名称.findOne({条件文档})
  • 方法pretty():将结果格式化
    • db.集合名称.find({条件文档}).pretty()

比较运算符

  • 等于:默认是等于判断,没有运算符
  • 小于:$lt (less than)
  • 小于等于:$lte (less than equal)
  • 大于:$gt (greater than)
  • 大于不等于:$gte
  • 不等于:$ne

db.stu.find({age:{gte:18}})

范围运算符

使用"$in","$nin"判断是否在某个范围内

查询年龄为18、28的学生

db.stu.find({age:{$in[18,28,38]}})

逻辑运算符

  • and :在json中写多个条件即可

    查询年龄大于或等于18,并且性别为true的学生

    db.stu.find({age:{$gte18},genter:true})

  • or:使用$or,值为数组,数组中每个元素为json

    查询年龄大于18,或性别为false的学生

    db.stu.find({$or:[{age:{$gt:18}},{gender:false}]})

  • 查询年龄大于18或性别为男生并且姓名是郭靖

    db.stu.find({$or:[{age:{$gt:18}},{gender:false}],name:'gj'})

使用正则表达式

使用//或$regex编写正则表达式

查询姓黄的学生

db.products.find({sku:/^abc/})

limit和skip

  • 方法:limit():用于读取指定数量的文档

    db.集合名称.find().limit(number)

    查询2条学生信息

    db.stu.find().limit(2)

  • 方法skip():用于跳过指定数量的文档

    db.集合名称.find().skip(number)

    db.stu.find().skip(2)

  • 同时使用

    db.stu.find().limit(2).skip(3)

自定义查询

使用$where 后面写一个函数,返回满足条件的数据
查询年龄大于30的学生
db.stu.find({
$where:finction(){
return this.age>30
}
})

投影

在查询的返回结果中,只选择必要的字段
db.集合名称.find({},{字段名称:1,....})

排序

方法sort(),用于对集合进行排序

db.集合名称.find().sort({字段:1,....})

  • 参数1 为升序排列
  • 参数2 为降序排列

统计个数

方法count()用于统计结果集中文档条数

五、mongodb聚合

聚合 aggregate

聚合是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组,过滤等功能,然后经过一系列的处理,输出相应的结果。

​ db.集合名册.aggregate({管道:{表达式}})

常用管道

在mangodb中,文档处理完毕后,通过管道进行下一次处理

常用管道如下:

  • $group: 将集合中的文档分组,可用于统计结果

  • group bu null:将集合中所有文档分为一组

  • $match: 过滤数据,只输出符合条件的文档

  • $project: 修改输入文档的结构,如重命名、增加、删除字段、创建计算结果

  • $sort: 将输入文档排序后输出

  • $limit: 限制聚合管道返回的文档数

  • $skip: 跳过指定数量的文档,并返回余下的文档

  • $unwind: 将数组类型的字段进行拆分,将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值

表达式

处理输入文档并输出

语法:表达式:'$列名'

常用表达式:

  • $sum: 计算总和,$sun:1表示以一倍技数
  • $avg: 计算平均值
  • $min: 获取最小值
  • $max: 获取最大值
  • $push: 在结果文档中插入值到一个数组中
  • $first: 根据资源文档的排序获取第一个文档数据
  • $last: 根据资源文档的排序获取最后一个文档数据

六、备份、恢复、索引

备份

备份的语法:
mongodump -h dbhost -d dbname -o dbdirectory
-h:服务器地址,也可以指定端口号
-d:需要备份的数据库名称
-o:备份的数据存放的位置,此目录中存放着备份出来的数据

恢复

恢复语法:
mongorestore -h dnhost -d dbname --dir dbdirectory
-h:服务器地址
-d:需要恢复的数据库实例
--dir:备份数据所在位置

索引

以提升查询速度

mongodb mysql redis的区别和使用场景

  • mysql是关系型数据库,支持事物
  • mongodb,redis非关系型数据库,不支持事物
  • mysql,mongodb,redis的使用根据如何方便进行选择
    • 希望速度快的时候,选择mongodb或者是redis
    • 数据量过大的时候,选择频繁使用的数据存入redis,其他的存入mongodb
    • mongodb不用提前建表建数据库,使用方便,字段数量不确定的时候使用mongodb
    • 后续需要用到数据之间的关系,此时考虑mysql

爬虫数据去重,实现增量式爬虫

  • 使用数据库建立关键字段(一个或者多个)建立索引进行去重

  • 根据url地址进行去重

    • 使用场景:

      • url地址对应的数据不会变的情况,url地址能够唯一判别一个条数据的情况
    • 思路
      • url存在redis中
      • 拿到url地址,判断url在redis的url的集合中是够存在
      • 存在:说明url已经被请求过,不再请求
      • 不存在:url地址没有被请求过,请求,把该url存入redis的集合中
    • 布隆过滤器
      • 使用多个加密算法加密url地址,得到多个值
      • 往对应值的位置把结果设置为1
      • 新来一个url地址,一样通过加密算法生成多个值
      • 如果对应位置的值全为1,说明这个url地址已经抓过
      • 否则没有抓过,就把对应位置的值设置为1
  • 根据数据本省进行去重

    • 选择特定的字段,使用加密算法(md5,sha1)讲字段进行假面,生成字符串,存入redis的集合中
    • 后续新来一条数据,同样的方法进行加密,如果得到的字符串在redis中存在,说明数据存在,对数据进行更新,否则说明数据不存在,直接插入

MongoDB_走一波的更多相关文章

  1. 深入理解MVC C#+HtmlAgilityPack+Dapper走一波爬虫 StackExchange.Redis 二次封装 C# WPF 用MediaElement控件实现视频循环播放 net 异步与同步

    深入理解MVC   MVC无人不知,可很多程序员对MVC的概念的理解似乎有误,换言之他们一直在错用MVC,尽管即使如此软件也能被写出来,然而软件内部代码的组织方式却是不科学的,这会影响到软件的可维护性 ...

  2. C#+HtmlAgilityPack+Dapper走一波爬虫

    最近因为公司业务需要,又有机会撸winform了,这次的需求是因为公司有项目申报的这块业务,项目申报前期需要关注政府发布的相关动态信息,政府部门网站过多,人工需要一个一个网站去浏览和查阅,有时候还会遗 ...

  3. ES6走一波 数组的扩展

    Array flat 数组实例的扁平化方法(浏览器支持不佳) 建议使用 lodash的 flatten

  4. ES6走一波 字符串的扩展

    ES6字符串扩展: 处理大码点字符 字符的Unicode表示法 \uxxxx表示一个字符串,超出 \u0000 ~ \uffff范围,必须用两个双字节形式表示. ES6改进为 将码点放到大括号 可正确 ...

  5. ES6走一波 Iterator

    Iterator---> for ... of 循环 Generator函数原生具有 Iterator接口,所以可采用数组的形式解构赋值

  6. ES6走一波 变量结构赋值

    Destructuring  变量的解构赋值 是一种模式匹配 ES6我关注点之一是用途  能否举些好例子是检验学习到位的方法之一 交换变量值 函数返回多个值 函数入参为对象.数组,内部使用更简洁 意义 ...

  7. ES6走一波 module

    ES6模块设计思想:  尽量静态化,使得编译时就能确定模块的依赖关系,输入.输出的变量.可做静态优化. ES6模块不是对象,而是通过export命令显示指定输出的代码,再通过import命令输入 ex ...

  8. ES6走一波 Proxy/Reflect

    Proxy:像拦截器,对目标对象修改等进行拦截,是一种元编程(meta programming),即修改JS语言本身. //生成proxy实例,两个参数都是对象,targetObj是要拦截的目标对象, ...

  9. ES6走一波 Generator异步应用

    Generator 函数的异步应用 JS异步编程 callback Promise(解决回调地狱) 事件 发布订阅 generator Thunk函数  屁股函数 两次高阶调用的函数 第一次调用的入参 ...

随机推荐

  1. OSDA - 一个以MIT协议开源的串口调试助手

    市场其实有很多开源的串行端口调试助手(Open Serial Port debug assistant),但其中很大一部分没有明确的开源协议,还有一部分只限个人使用,所以编写了一个并以MIT协议授权开 ...

  2. js排序专场

    1,冒泡排序 function bubble(arr) { var len = arr.length - 1; for (let i = 0 ; i < len; i++) { var bool ...

  3. [HNOI2008] 玩具装箱 D2 T3 斜率优化DP

    Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再放到一种特殊的一维容器中.P教授有编号为1... ...

  4. 修改ssh主机名

    三台机器的配置相似,以zk1为例 1.修改hostname vi /etc/hostname zk1 2.修改hosts文件 vi /etc/hosts 10.45.48.233 zk1 10.45. ...

  5. MyBatis从入门到精通(第3章):MyBatis注解方式的基本使用

    MyBatis 注解方式就是将 SQL 语句直接写在DAO层的接口上. 在黑马录制的2018年双元视频课:\08 SSM整合案例[企业权限管理系统]\07.订单操作  有使用MyBatis注解进行多表 ...

  6. 面向对象-接口(interface)实战案例

    面向对象-接口(interface)实战案例 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.接口(interface)概述 1>.接口的语法格式 接口时抽象类的一种特殊体 ...

  7. POJ 3994:Probability One

    Probability One Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1674   Accepted: 1151 D ...

  8. Java算法练习——罗马数字转整数

    题目链接 题目描述 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 ...

  9. bzoj 4236JOIOJI

    一开始忘掉特殊情况也是蛋疼2333(有一直到头的.mp[0][0]是要特判的) 做法也就是找mp[i][j]相同的东西.(貌似可以写成线性方程组(z=x+A,z=y+B)过这个的就是相等(可以先从2维 ...

  10. discuz伪静态问题(简单)

    提前声明一下我用的是宝塔面板.Linux系统.Nginx Web Server.经过一上午的摸索(我很菜了),终于在一个很无语的地方成功搞了伪静态1.2.点击查看当前的 Rewrite 规则3.我的是 ...