MongoDB是一个基于分布式 文件存储的NoSQL数据库,适合存储JSON风格文件的形式。

  • 三元素:数据库、集合和文档。

    • 文档:对应着关系数据库中的行,就是一个对象,由键值对构成,是json的扩展Bson形式,示例

      {'name':'guojing','gender':'男'}
    • 集合:类似于关系数据库中的表,储存多个文档,结构不固定,示例
      {'name':'guojing','gender':'男'}
      {'name':'huangrong','age':18}
      {'book':'shuihuzhuan','heros':'108'}

一、环境安装与运行

  • 安装

    sudo apt-get install mongodb

  配置文件为 /etc/mongodb.conf,默认端口号:27017

  • 启动服务器

    sudo service mongodb start  #相当于执行命令 sudo mongod --config /etc/mongod.conf
  • 关闭服务器

    sudo service mongodb stop
  • 重启服务器

    sudo service mongodb restart #修改了配置文件/etc/mongodb.conf后,需要重启mongodb服务器让配置生效
  • 启动客户端

    sudo mongo

二、数据库操作

  • 查看当前数据库

    db
  • 查看所有数据库

    show dbs
  • 切换(或创建)数据库

    use 数据库名

    切换数据库,如果数据库不存在,当插入数据或创建集合时,会自动创建这个数据库

  • 删除数据库

    db.dropDatabase()

    删除当前指向的数据库,如果不存在,则什么也不做

三、集合操作

  • 创建

    db.createCollection(name[,options])
    #name集合名称
    #options可选,是一个用于指定集合配置的文档,其中capped参数默认不设置上限(false),若设置上限(true)则需要指定参数size,单位字节
    #不设置集合大小
    db.createCollection("stu")
    #设置集合大小
    db.createCollection("sub", { capped : true, size : 10 } )
  • 查看当前数据库集合

    show collections
  • 删除集合

    db.集合名.drop()

四、数据操作

  • 插入

    db.集合名.insert(文档) 或 db.集合名.insert([文档...])
    #如果不指定_id字段,则分配一个唯一的ObjectId;如果指定_id字段,且_id已经存在时,不做任何操作;如果一次性插入多条数据,以数组的方式传入文档
    # 不指定_id
    db.stu.insert({name:'gj',gender:1}) #指定_id
    s1={_id:'20160101',name:'hr'}
    s1.gender=0
    db.stu.insert(s1)
  • 删除--(注意justOne参数)

    db.集合名.remove(条件,{justone:<boolean>}) #参数justOne默认false,删除多条
    # 只删除匹配到的一条数据
    db.stu.remove({gender:0},{justOne:true}) #删除所有
    db.stu.remove({})
  • 修改--(注意$set以及multi参数)

    db.集合名.update({条件},$操作符,{multi: <boolean>}]) #参数multi只和$操作符一起使用,默认false,只修改一条数据,true表示修改多条数据
    # 不使用操作符$set,修改整条文档
    db.stu.update({name:'hr'},{name:'mnc'}) #使用操作符$set指定属性修改
    db.stu.update({name:'hr'},{$set:{name:'hys'}}) #multi参数和$set一起使用,修改多条文档
    db.stu.update({},{$set:{gender:0}},{multi:true})
  • 保存

    db.集合名.save(document) 
    #在手动插入_id字段时,如果_id已经存在,做全文档更新操作,其余均表示插入数据。
    db.stu.save({_id:'20160102','name':'yk',gender:1})
    db.stu.save({_id:'20160102','name':'wyk'}) #对上述文档做修改
  • 查询

    • 基本查询

      db.集合名.find({条件文档}) #查询所有
      db.集合名.findOne({条件文档}) #只查询第一条
      db.集合名.find({条件文档}).pretty() #结果格式化输出
    • 比较运算符

      • 等于:默认,没有运算符
      • 小于: $lt
      • 小于等于: $lte
      • 大于:$gt
      • 大于等于:$gte
      • 不等于:$ne
        #查询年龄大于等于18的学生
        db.stu.find({"age":{$gte:18}})
    • 逻辑运算符

      • 逻辑与:默认
      • 逻辑或:$or
        # 查询年龄大于或等于18,并且性别为1的学生
        db.stu.find({"age":{$gte:18},"gender":1}) #查询年龄大于18,或性别为0的学生
        db.stu.find({$or:[{"age":{$gt:18}},{"gender":1}]}) #查询年龄小于18或者大于20,性别为1的学生
        db.stu.find({$or:[{"age":{$lt:18}},{"age":{$gt:20}}],"gender":1})
    • 范围运算符

      • 在某个范围$in,后面接数组
      • 不在某个范围$nin,后面接数组
        #查询年龄18、20以及22岁的学生
        db.stu.find({"age":{$in:[18,20,22]}}) #查询年龄不等于18或20的学生
        db.stu.find({"age":{$nin:[18,20]}})
    • 正则表达式

      • 使用/表达式/或者$regex

        #查询姓黄的学生
        db.stu.find({"name":/^黄/})
        db.stu.find({"name":{$regex:"^黄"}})
    • 自定义查询

      • 使用$where:function(){return 满足条件的数据表达式}------运算符使用js语法,比如逻辑与(&&),逻辑或(||)

        #查询年龄18-22的学生
        db.stu.find({$where:function(){return this.age>18 && this.age<22}}) #查询年龄小于18或者大于22的学生
        db.stu.find({$where:function(){return this.age<18 || this.age>22}})
    • 投影

      • 只显示部分字段

        db.集合名.find({条件},{字段名:1,...}) #1表示该字段显示,0不显示;_id列默认显示,不显示需要明确设置为0
        #查询姓名和年龄(显示_id)
        db.stu.find({},{name:1,gender:1}) #查询姓名和年龄(不显示_id)
        db.stu.find({},{_id:0,name:1,gender:1})
    • skip

      • 跳过指定数量的文档

        db.集合名.find({条件}).skip(number) #number默认为0
        #查询从第3条开始的学生信息
        db.stu.find().skip(2)
    • limit

      • 读取指定数量的文档

        db.集合名.find({条件}).limit(number) #不写number参数,默认读取所有文档
        #读取3条学生信息
        db.stu.find().limit(3)
    • skip和limit合用

      • 不区分先后顺序

        #查询第5-9条学生信息
        db.stu.find().skip(4).limit(5) #相当于跳过4条数据,选5条
    • sort

      • 对结果集进行排序

        db.集合名称.find({条件}).sort({字段:1,...}) #1表示升序,-1表示降序
        #根据性别降序,再根据年龄升序
        db.stu.find().sort({"gender":-1,"age":1})
    • count

      • 对结果集中文档数目进行统计,返回整数

        db.集合名.find({条件}).count()
        或者
        db.集合名.count({条件})
        #统计年龄大于20的男生人数
        db.stu.count({"age":{$gt:20},"gender":1})
    • distinct

      • 对数据去重,返回的是一个列表

        db.集合名.distinct("字段名",{条件}) 

五、聚合(aggregate)

  • 聚合主要用于计算数据,类似sql中的sum()、avg()

    db.集合名.aggregate([{管道:{表达式}}...])
  • 管道

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

    • 常用管道:

      • $group:将集合中的文档分组,可用于统计结果
      • $match:过滤数据,只输出符合条件的文档
      • $project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果
      • $sort:将输入文档排序后输出
      • $limit:限制聚合管道返回的文档数
      • $skip:跳过指定数量的文档,并返回余下的文档
      • $unwind:将数组类型的字段进行拆分
  • 表达式

    • 处理输入文档并输出

    • 语法:表达式:‘$字段名’

    • 常用表达式:

      • $sum:计算总和,$sum:'$字段'表示求和,注意$sum:1表示计数,
      • $avg:计算平均值
      • $min:获取最小值
      • $max:获取最大值
      • $push:在结果文档中插入值到一个数组中(以列表的方式显示字段值)
      • $first:根据资源文档的排序获取第一个文档数据
      • $last:根据资源文档的排序获取最后一个文档数据
  • $group

    • 文档分组,用于统计结果
    • _id表示分组的依据,使用某个字段的格式为'$字段'
      # 统计男、女生人数
      db.stu.aggregate([{$group:{"_id":'gender',"couter":{$sum:1}}}])
      #结果文档中显示_id和counter的值
    • _id按照null分组,会将集合中所有文档分为一组
      # 求学生总人数和平均年龄
      db.stu.aggregate([{$group:{_id:null,counter:{$sum:1},average_age:{$avg:"$age"}}}])
    • 使用$$ROOT可以将文档内容加入到结果集的数组中
      #统计男、女生信息
      db.stu.aggregate([{$group:{_id:"$gender",objects:{$push:"$$ROOT"}}}])
  • $match

    • 过滤数据,输出符合条件文档

      #查询年龄大于20的学生
      db.stu.aggregate([{$match:{age:{$gt:20}}}]) #查询年龄大于20的男、女生人数
      db.stu.aggregate([{$match:{age:{$gt:20}}},{$group:{_id:"$gender",counter:{$sum:1}}}])
  • $project

    • 修改输出文档的结构

      #查找学生姓名、年龄
      db.stu.aggregate([{$project:{"_id":0,"name":1,"age":1}}]) #查询男生、女生人数,但仅输出人数
      db.stu.aggregate([{$group:{_id:'$gender',counter:{$sum:1}}},{$project:{_id:0,counter:1}}])
  • $sort

    • 将输入文档排序后输出

      #查询学生信息,按年龄升序
      db.stu.aggregate([{$sort:{age:1}}]) #查询男生、女生人数,按人数降序
      db.stu.aggregate([{$group:{_id:'$gender',counter:{$sum:1}},{$sort:{counter:-1}}])
  • $limit

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

      #查询2条学生信息
      db.stu.aggregate([{$limit:2}])
  • $skip

    • 跳过指定数量的文档,并返回余下的文档,$skip和$limi合用时,注意先写skip,再写limit

      #查询从第3条开始的学生信息
      db.stu.aggregate([{$skip:2}]) #统计男生、女生人数,按人数升序,取第二条数据
      db.stu.aggregate([{$group:{_id:"$gender",counter:{$sum:1}}},{$sort:{"counter":1}},{$skip:1},{$limit:1}])
  • $unwind

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

      db.集合名称.aggregate([{$unwind:'$字段名称'}]) 

六、索引

  • 提升查询速度

  • 创建大量数据

    for(var i=0;i<1000000;i++){db.stu.insert({name:'test'+i,num:i})}
  • 性能分析工具:explain("executionStats")

    查询语句.explain("executionStats")

    'millis'后面显示的是查询时间,单位ms

  • 建立索引

    db.集合.ensureIndex({属性:1或-1}) #1表示升序,-1表示降序,建立后的索引名称为"属性_1"或者"属性_-1"

    例如:db.stu.ensureIndex({name:1}),建立后的索引名称为"name_1"

  • 建立唯一索引

    db.集合.ensureIndex({属性:1},{"unique":true})
  • 建立联合索引

    db.集合名.ensureIndex({属性1:1,属性2:1...})
  • 查看索引

    db.集合名.getIndexes()
  • 删除索引

    db.集合名.dropIndex("索引名称") 

七、数据库安全

为了更安全的访问mongodb,需要访问者提供用户名和密码,于是需要在mongodb中创建用户。mongodb数据库采用了角色-用户-数据库的安全管理方式。

  • 常用系统角色如下:

    • root:只在admin数据库中可用,超级账号,超级权限
    • Read:允许用户读取指定数据库
    • readWrite:允许用户读写指定数据库
  • 创建超级管理用户:

    use admin #首先切换到admin数据库
    
    db.createUser({
    user:'用户名',
    pwd:'密码',
    roles:[{role:'root',db:'admin'}]
    })
  • 启用安全验证

    • 修改配置文件( /etc/mongodb.conf)

      #noauth = true
      auth = true #开启安全验证
    • 重启服务

      sudo service mongodb restart
    • 终端连接

      # sudo mongo -u '用户名' -p '密码' --authenticationDatabase '数据库名'
      sudo mongo -u 'admin' -p '密码' --authenticationDatabase 'admin'
  • 普通用户管理

    • 首先使用超级管理员登陆,然后再进行用户管理操作

    • 创建普通用户

      db.createUser({
      user:'用户名',
      pwd:'密码',
      roles:[{role:'readWrite',db:'数据库名'}...] #数组里可以有多个角色文档,比如用户在不同的数据库里都有读写权限
      })
    • 查看当前数据库的用户

      show users
    • 修改用户:可以修改pwd、roles属性

      db.updateUser('用户名',{pwd:'新密码',roles:[{'新角色'}...]})
    • 删除用户

      use admin  #切换到admin数据库
      db.system.users.remove(条件)
    • 终端连接

       sudo mongo -u '用户名' -p '密码' --authenticationDatabase '数据库名' 

八、复制

复制提供了数据的冗余备份,并在多个服务器上存储数据的副本,允许从硬件故障和服务中断中恢复数据,能够实现无宕机维护(自动故障转移与自动恢复)。

复制至少需要2个节点,其中1个为主节点,其它均为从节点。任何节点均可以成为主节点。

主节点负责所有写入操作,从节点定期轮询主节点获取这些操作并执行这些操作,从而保证从节点的数据与主节点一致。

  • 设置复制节点

    • 创建数据库文件存放目录(自定义)

      mkdir ~/Desktop/t1
      mkdir ~/Desktop/t2
    • 使用如下格式启动mongod,如果在同一台主机上,注意port不能相同,replSet的名称必须是一致的(名称可以自定义)

      sudo mongod --bind_ip 192.168.196.128 --port 27017 --dbpath ~/Desktop/t1 --replSet rs0
      sudo mongod --bind_ip 192.168.196.128 --port 27018 --dbpath ~/Desktop/t2 --replSet rs0
    • 连接主服务器(自定义一个)

      sudo mongo --host 192.168.196.128 --port 27017
    • 初始化

      rs.initiate()

      哪个服务器执行初始化,哪个服务器就作为主节点,rs是mongo服务器中专门用于复本集操作的内置对象

    • 查看当前状态

      rs.status()
    • 添加副本集

      rs.add("192.168.127.128:8899")
    • 连接从服务器

      sudo mongo --host 192.168.196.128 --port 27018
    • 从服务器设置

      rs.slaveOk()

      主服务器插入数据,从服务器就可以读取数据了

    • 删除从节点

      rs.remove('192.168.196.128:27018') #需要在主服务器操作

      关闭主服务器后再重新启动,会发现原来的从服务器变为了主服务器,新启动的服务器(原来的主服务器)变为了从服务器,但是注意重新设置rs.slaveOk()

九、备份与恢复

  • 备份

    • 语法

      sudo mongodump -h 服务器地址 -d 需要备份的数据库 -o 备份数据存放目录
      mkdir ~/Desktop/test1_bak #创建存放备份数据的目录
      sudo mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1_bak
  • 恢复

    • 语法

      sudo mongorestore -h 服务器地址 -d 恢复后数据库名 --dir 备份数据所在位置
      sudo mongorestore -h 192.168.196.128:27017 -d test2 --dir ~/Desktop/test1_bak/test1

十、python交互

  • 安装pymongo包

    sudo pip3 install pymongo
  • 引入包

    import pymongo
  • 建立连接并创建客户端

    有安全认证:client=MongoClient("mongodb://用户名:密码@host:27017/数据库名称")
    无安全认证:client=MongoClient("mongodb://localhost: 27017")
  • 获得数据库(以test数据库为例)

    db = client.数据库名
    例如:db = client.test
  • 获得集合stu

    stu = db.stu
  • 数据操作

    • 查询

      • find_one 查找单个文档

        stu1 = stu.find_one({条件}) #返回一条文档,字典类型
      • find 查找多个文档
        cursor = stu.find({条件}) #返回迭代器对象cursor
        #方式1:用for循环迭代取值
        for s in cursor:
        print(s) #字典类型 #方式2:用next取值
        s1 = next(cursor)
        s2 = next(cursor)
        ...
    • 插入

      • insert_one 插入一条文档

        stu.insert_one(文档)
      • insert_many 插入多条文档
        stu.insert_many([文档1,文档2...])
    • 更新

      • update 更新匹配到的第一条整条文档

        stu.update({条件},文档) #注意条件中的数字一定要写成字符串类型
      • update_one 与$set一起使用,指定属性修改匹配到的第一条文档
        stu.update_one({条件},{$set:{文档}})
      • update_many 与$set一起使用,指定属性修改多条文档
        stu.update_many({条件},{$set:{文档}})
    • 删除

      • delete_one 删除单条文档

        stu.delete_one({条件})
      • delete_many 删除多条文档
        stu.delete_many({条件})

MongoDB数据库的使用的更多相关文章

  1. Mongodb数据库学习系列————(一)Mongodb数据库主从复制的搭建

    Mongodb数据库主从复制的搭建 Writeby:lipeng                                    date:2014-10-22 最近项目上用到了位置查询,在网上 ...

  2. 基于C#的MongoDB数据库开发应用(4)--Redis的安装及使用

    在前面介绍了三篇关于MongoDB数据库的开发使用文章,严格来讲这个不能归类于MongoDB数据库开发,不过Redis又有着和MongoDB数据库非常密切的关系,它们两者很接近,Redis主要是内存中 ...

  3. FineReport如何连接和使用MongoDB数据库

    随着NoSQL数据库越来越流行,MongoDB数据库作为NoSQL数据库中的领头羊,使用也越来越广泛.为此,FineReport V8.0版本提供了数据连接和数据集接口,可以通过开发一款可以连接和使用 ...

  4. python操作mongodb数据库

    一.MongoDB 数据库操作 连接数据库 import pymongo conn = pymongo.Connection() # 连接本机数据库 conn = pymongo.Connection ...

  5. NoSql 中Mongodb数据库的使用

    1.NoSql数据库简介 2.MongoDB数据库的简介 3.MongoDB下Windows下的安装

  6. 线上mongodb数据库mLab使用总结

    最近在CNode社区看到有人分享了免费的线上mongodb数据库(容量500M),今天去注册了一下,成功的将线下数据库替换掉了,现在就说一下它的使用和配置需要注意的地方: mLab是一款免费的在线mo ...

  7. mongoDB数据库和Spring MVC的整合

    之前一直用到的项目是Spring MVC+maven+mysql的,最近有些数据需要用到mongoDB数据库,现在做一些总结. 第一步:加载jar.maven配置 <!-- mongodb开始 ...

  8. 【转载】CentOS6.5_X64下安装配置MongoDB数据库

    [转载]CentOS6.5_X64下安装配置MongoDB数据库 2014-05-16 10:07:09|  分类: 默认分类|举报|字号 订阅      下载LOFTER客户端 本文转载自zhm&l ...

  9. 基于C#的MongoDB数据库开发应用(3)--MongoDB数据库的C#开发之异步接口

    在前面的系列博客中,我曾经介绍过,MongoDB数据库的C#驱动已经全面支持异步的处理接口,并且接口的定义几乎是重写了.本篇主要介绍MongoDB数据库的C#驱动的最新接口使用,介绍基于新接口如何实现 ...

  10. 基于C#的MongoDB数据库开发应用(2)--MongoDB数据库的C#开发

    在上篇博客<基于C#的MongoDB数据库开发应用(1)--MongoDB数据库的基础知识和使用>里面,我总结了MongoDB数据库的一些基础信息,并在最后面部分简单介绍了数据库C#驱动的 ...

随机推荐

  1. web components & publish custom element & npm

    web components & publish custom element & npm https://www.webcomponents.org/publish Polymer ...

  2. how to write an ebook that can support published by format PDF, Epub, Mobi and so on

    how to write an ebook that can support published by format PDF, Epub, Mobi and so on 如何写一本自己的电子书,支持各 ...

  3. npm & cmd & bash & bin

    npm & cmd & bash & bin bin node_modules & nested npm publish & all src files npm ...

  4. alipay 小程序 & online IDE & demos

    alipay 小程序 & online IDE & demos system-info iOS / Andriod https://opendocs.alipay.com/mini/a ...

  5. js 获取是否为闰年,以及各月的天数 & isLeapYear

    js 获取是否为闰年,以及各月的天数 calendar utils isLeapYear const isLeapYear = (year) => { return (year % 4 === ...

  6. Flutter: SliverAppBar 应用程序栏与滚动视图集成,以便它可以根据滚动偏移量在高度上变化

    API class _MyHomeState extends State<MyHome> with SingleTickerProviderStateMixin { @override W ...

  7. Flutter: 下拉刷新,上拉加载更多

    import 'package:flutter/material.dart'; import 'package:english_words/english_words.dart'; void main ...

  8. Redis高频面试题总结

    通过面试多家大型互联网企业,总结了如下的高频面试题目: 1.redis 过期键的删除策略? (1)定时删除:在设置键的过期时间的同时,创建一个定时器 timer). 让定时器在键的过期时间来临时,立即 ...

  9. JDBC概念理解

    ##JDBC: 概念:Java DataBase Connectivity  Java 数据库连接  Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套操作所有关系型数据库的规则 ...

  10. Pyqt5——变色的表格

    需求:鼠标左键点击表格后,对应的单元格背景颜色发生变化. 实现:(1)使用Qt的model-view模式生成表格视图. (2)重写表格的点击事件. (3)设置表格的背景颜色. 正常情况下,当用户选中单 ...