MongoDB——理论及使用命令详解 数据库

数据存储阶段

  文件管理阶段(.txt  .doc .xls)

  优点:

    1 使用简单,展现直观

    2 可以长期保存数据

    3 可存储数据量比较大

  缺点:

    1 查找不方便,

    2 容易造成数据冗余,

    3 格式不规范

数据库管理阶段

  优点: 

    1 将数据结构化存储,降低冗余

    2 提高了增删改查效率

    3 方便扩展,方便程序调用

  缺点:

    数据库往往需要指令或语句操作,相对复杂

  几个概念:

    数据:能够输入到计算机中并被识别处理的信息的集合

    数据结构:组成一个数据集合的数据之间的关系

    数据库:

      按照一定的数据结构,存储数据的仓库,数据库是在数据库管理系统管理和控制下,在一定介质上的数据集合

    数据库管理系统:数据库管理软件,用于建立维护操作数据库

    数据库系统: 由数据库和数据库管理系统高等组成的集合

关系型数据库

  采用关系模型(二维表) 来组织数据结构的数据库

    Oracle  DB2  SQLServer  Mysql  SQLite

  优点:

    1 容易理解,逻辑类似常见的表格

    2 使用方便,都使用sql语句,sql语句非常成熟

    3 数据一致性高,冗余低,数据完整性好,便于操作

    4 技术成熟,功能强大,支持很多复杂操作

  缺点:

    1 * 每次操作都要进行sql语句的解析,消耗较大

    2 * 能很好的满足并发的需求,特别是少量数据爆发,关系型数据库读写能力会显得不足

    3 *关系型数据库往往每一步都要进行加锁的操作,也造成了数据库的负担

    4 *数据一致性高,有时也会使数据的存储不灵活

非关系型数据库(Not Only sql)

    优点:

      1 高并发,读写能力强

      2 弱化数据结构一致性,使用灵活

      3 有良好的可扩展性

    缺点:

      1 通用性差:没有sql 语句那样同于的语句

      2 操作灵活导致容易出错和混乱

      3 没有外键关联等复杂的操作

    nosql的使用情况

    1 ,对数据存储灵活性要求高,一致性要求低

    2 , 数据处理海量并发,要求瞬间效率速度比较高

    3 ,数据比较容易建立 Nosql模型

    4 ,网站临时缓冲存储,爬虫应用 

非关系型数据库和关系型 数据库比较

    1 不是以关系模型构建的,结构自由

    2 非关系型数据库不保证数据的一致性

    3 非关系型数据库可以在处理高并发和海量数据时弥补关系型数据库的不足

    4 非关系型数据库在技术上没有关系型数据库成熟也没有SQL语句的操作

Nosql分类

  1 键值型数据库 Redis

  2 文档型数据库  MongoDB

  3 列存储数据库  HBase

  4 图形数据库

MongoDB数据库

  标签:  非关系型数据库   文档型数据库

      最像关系型的非关系型数据库

  特点:

    1 由C++编写的数据库管理系统

    2 支持丰富的数据操作,增删改查索引聚合

    3 支持丰富的数据类型

    4 使用方便,可以很好的扩展。相对比较成熟

    5 支持众多的编程语言接口(python, php c++ c#)

自动安装

sudo apt-get install mongodb

默认安装位置 : /var/lib/mongodb

配置文件位置 :/etc/mongodb.conf

命令集:: /usr/bin  |  /usr/local/bin  

手动安装

  1 下载安装包

  2 解压安装包

  3 将解压后的MongoDB文件夹中的bin目录添加到环境变量

    PATH=$:/opt/mongo...../bin

    export PATH

    将以上两句写入启动脚本  /etc/rc.local

  4 重启

mongodb命令

  设置数据库存储位置

    mongod --dbpath 【目录】

    mongod --dbpath dbs  【将存储路径设置为dbs】

  设置数据库监听端口

    *mongod --port 8080

    *默认监听商品是27017

  mongo  进入数据库交互操作界面

  mongo shell  :  用来操作mongodb 数据库的界面,在这里可以使用mongo语句操作数据库内容

  退出shell :  quit()  exit  ctrl+c

  组织结构:键值

  创建数据库

    use databaseName

    use stu  创建一个名为stu的数据库

    * use 实际为选择使用哪个数据库,当数据库不存在时会自动创建

    * use 后并不会立即创建出数据库,而是需要等到插入数据时数据库才会创建

  查看系统中的数据库

    show dbs  

  系统数据库说明

    admin : 存储用户信息 

    local :存储本地数据

    config :存储分片信息

  数据库命名规则

    1 使用UTF-8字符(mongo默认支持utf-8)

    2 不能含有空格 . / ''  字符

    3 长度不超过64字节

    4 不能和系统数据库重名

  db : mongodb的全局量,代表当前正在使用的数据库

  * 如果不选择使用任何数据库db代表test,直接插入数据就会建立test数据库

  数据库的备份和恢复:

    备份 mongodump -h host -d dbname -o bak

      mongodump -h 127.0.0.1 -d test -o bak

    恢复 mongorestore -h dbhost:port -d dbname path

      mongorestore -h 127.0.0.1:27017 -d  res bak/stu

  mongostat 监控操作命令

    query:  查

    flushes:每秒和磁盘交互次数

    vsize :   虚拟内存

    res  : 物理内存

    time  : 时间 

  mongotop 监控数据库读写时长

    ns  数据表

    total 总时间

    read 读时间

    write 写时间

  删除数据库

    db.dropDatabase()

      删除db所代表的数据库

  创建集合

    方法1

       db.createCollection( Collection_name )  

      db.createCollection('class1')

    方法2 

      当向一个集合中插入数据的时候如果集合不存在则自动创建

      db.collection_name.insert(...)

      db.class2.insert({'a':1})

   查看数据库中集合

    show collections

    show tables

  集合命名规则

    1 合法的utf-8 字符

    2 不能有 ''

    3 不能以system. 开头,因为这是系统保留集合前缀

    4 不能和关键字重名

  删除集合

    db.collection.drop()

    db.class.drop() 删除集合class

  集合的重命名

    db.collection.renameCollection('new_name')

    db.class2.renameCollection('class0') 将class2集合重命名为class0

文档

  mogodb中数据的组织形式 ---》》文档

  mongodb  文档:是以键值对的形成组成的一组数据。类似python中字典描述数据的方式

  键:即文档的域,表达了一个键值对的含义

    键的命名规则:

    1 utf-8格式字符串

    2 不能使用 ‘’

    3 一个文档中的键不能重复

  值:即文档存储的数据。

    * 文档中键值对是有序的

    * 文档中键值对严格区分大小写

      bson ---> json ---> javascript

    类型          值

    整型          整数 1,2,3

    布尔类型        true ,false

    浮点型         小数

    Array          数组

    Date          时间日期

    Timestamp       时间戳

    String         字符串

    Symbol           特殊字符串

    Binary data      二进制字串

    Null           null空值

    code          js代码

    Object         内部文档(对象)    

    regex          正则字串

    ObjectId        自动生成ID标记

    "_id" : ObjectId("5ba0a0d78d56be714c54927c")

    _id : 当mongodb插入文档时如果不指定_id域则自动生成_Id域。值如果不自己指定即会自动生成一个ObjectId值

    5ba0a0d78d56be714c54927c

      24位16进制,使用ObjectId经过算法处理保证其唯一性

      其中8 位  文档创建时间   后面 6位 机器ID  后面4位进程ID  后面6位计数器

集合中的文档

  1 集合中的文档不一定有相同的域

    * 个数不同

    * 域不相同

    * 数据类型不同    

  2 集合中的文档各自比较独立,相互并不影响

集合创建原则

  1 集合中的文档要描述同一类事物

  2 数据库中同一类数据尽量集中存放在相同的集合

  3 集合中的文档嵌套层数不要太多

  

插入文档

  db.collection.insert()

    功能: 插入一个文档

    参数:要插入的文档

      db.class2.insert({'name':'lucy','sex':'w'})

    * 插入操作中键可以不加引号

    * 查看插入结果 db.class2.find()

    * _id 值可以自己插入,但是不能重复

    插入多条文档:   db.class2.insert([{}}db.class2.insert({'name':'lucy','sex':'w'})])

          等同于 db.class2.insertMany([{name:'lucy',age:18},{name:'alex',age:18}])

    

save 插入文档

  如果正常插入与insert用法相同

  db.collection.save()

  如果插入数据是由_id域,且_id域值存在时则会修改原有文档,如果该值不存在则正常插入

  获取集合对象方法

    db.class2. ==>db.getCollection('class2')

 查找操作:

  查找所有内容:

    db.collection.find() 等同于 select * from table;

  db.collection.find(query,field)  【query-->条件,,,field--> 字段】

    功能:查找文档

    参数:query 查找条件,相当于where子句

          field   查找的域

    返回值:查找到的所有文档

    query :以键值对方式传递参数,如果是空{}表示查找所有内容

      查找所有年龄为17 的文档

        db.class0.find({age:17})

    field :以键值对的方式给出要查找(不查找)的域以域名为键,以0,1为值分别表示不查找和查找

        * 如果某一个或者多个域设置为0,表示这些域不查找,其他域均查找

        * 如果某一个或多个域设置为1 ,表示这些域查找,其他域均不查找

        * _id除非设置为0,否则均会查找

        * 除_id域其他域不能有的设置为1 有的设置为 0

        db.class2.find({age:17},{_id:0,name:1})

        错误写法:::【db.class2.find({age:17},{_id:0,name:1,sex:0})  】

    findOne(query,field)

      功能:查找第一条符合条件的文档

      参数:同find

      返回值:返回查找到的文档

      db.class2.findOne({age:17},{_id:0,name:1})

    补充:通过find查找结果,可以使用序列号获取具体某一项

      获取查找结果中的第3项

      db.class.find()[2]

    

query 更多的筛选用法

  操作符:使用$符号注明的一个特殊字符串,表达一定的含义,比如$It   表示小于

  比较操作符

    $eq   等于   ==  db.class2.find({age:{$eq:17}},{_id:0,name:1,age:1})

    $lt     小于    <  db.class2.find({name:{$lt:'Tom'}},{_id:0})

    * 在mongondb中字符串可以比较大小

    $lte  小于等于 <=    db.class2.find({age:{$lte:18}},{_id:0})

    $gt  大于   >   db.class2.find({age:{$gt:18}},{_id:0})

    $gte  大于等于 >=  db.class2.find({age:{$gte:18}},{_id:0})

    $ne    不等于  !=  db.class2.find({age:{$ne:18}},{_id:0})

    * 使用ne查找也会找到该域不存在的文档

    $in  包含      db.class2.find({age:{$in:[17,18]}},{_id:0})  找到年龄为【17,18】的文档

    $nin  不包含    db.class2.find({age:{$nin:[18,17]}},{_id:0})

  逻辑操作符

    1 $and 

      * query 中如果多个条件用逗号隔开即为and关系

      db.class2.find({age:{$lt:18},sex:'w'},{_id:0})

    2 $and 逻辑与AND              查找 年龄小于18 and 性别为W的查询

      db.class2.find({$and:[{age:{$lt:18}},{sex:'w'}]},{_id:0})

    3 $or 逻辑或              查找年龄小于18 or 性别为L的

      db.class2.find({$or:[{age:{$lt:18}},{sex:'L'}]},{_id:0})

    4 $not 逻辑非               查找年龄不小于18的

      db.class2.find({age:{$not:{$lt:18}}},{_id:0})

    5 $nor                   查找 性别不w,且 年龄不为22 的

      db.class2.find({$nor:[{sex:'w'},{age:22}]},{_id:0})

    6 逻辑条件混合              查找 年龄大于17 且 为 M,或者姓名叫 sunny

      db.class2.find({$or:[{age:{$gt:17},sex:'m'},{name:'sunny'}]},{_id:0})

                         查找 年龄不大于18 或者 性别为w,  并且姓名大于Lucy的

      db.class2.find({$or:[{age:{$lte:18}},{sex:'w'}],name:{$gt:'Lucy'}},{_id:0})

    7 Array [1,2,3,4]

      * 数组是有序的数据集合

      * mongo中数组也可以有多重数据元素混合

      查找数组中包含某一条件的元素

       只要score数组中包含小于60的元素即可查询过滤

        db.class1.find({score:{$lt:60}},{_id:0})

    8  $all  查找数组同时包含多项的文档 

          db.class1.find({score:{$all:[67,66]}},{_id:0})

    9 $size  通过数组的元素个数查找  

      db.class1.find({score:{$size:2}},{_id:0})  

    10 $slice  显示数组中的指定项

        db.class1.find({},{_id:0,score:{$slice:2}})  显示数组前两项

        db.class1.find({},{_id:0,score:{$slice:[1,3]}})   显示数组索引  跳过第一个,显示后面2个

        * 这里的下标需要注意,和python中 标的用法不一样

    11 其它常用查找操作符

      $exists

        通过某个域是否存在筛选

        查找不存在sex域的文档

          db.class1.find({sex:{$exists:false}},{_id:0})

      $mod 余数查找

          找出年龄为双数的文档

        db.class1.find({age:{$mod:[2,0]}},{_id:0})

      $type 找出指定数据类型的文档

  

        碰到不知道的时候去官网查找资料  地址:【https://docs.mongodb.com/manual/reference/operator/query/exists/index.html

      

 查找结果的操作函数

   db.collection.distinct(field)

    功能:查看某个域的值范围

    示例,db.class1.distinct('name')

   

  pretty()

    功能:格式化显示查询结果

     db.class1.find().pretty()

  limit(n)

    功能:显示前n条结果

    db.class1.find({},{_id:0}).limit(3)

  skip(n)

    功能:跳过前n条显示后面的查询结构

    db.class1.find({},{_id:0}).skip(2)

  count()

    功能:统计查询结果数量

      统计性别为 w 的文档个数

      db.class1.find({sex:'w'},{_id:0}).count()

    * 在统计数量时要给出一定的query条件

  sort({field:1/-1})

    功能:对查找结果排序

    参数:以键值对表示按照哪个field排序

       1 表示升序,-1表示降序

    db.class1.find({},{_id:0}).sort({age:1})

    复合排序,年龄相同时,按照姓名降序  

    db.class1.find({},{_id:0}).sort({age:1,name:-1})

删除文档

  mongodb: db.collection.remove(query,justoOne)

    remove(query,justOne)

      功能:删除文档

      参数:query  用法同查找同find

         justOne  布尔值,默认为false,表示删除所有符合条件的文档

                   设置为true,表示只删除一条

      删除所有不存在sex域的文档

      db.class1.remove({sex:{$exists:false}})

      

      删除集合所有文档

        db.class2.remove({})

      

修改文档:

  db.collection.update(query,update,upsert,multi)

    功能:修改文档

    参数:query: 筛选条件,用法同find

         update: 要修改成什么内容,通常配合修改操作符(修改器)使用  

       upsert:布尔值:默认是false  如果query没有筛选到文档则不做任何操作

               如果设置为 true 则如果quety没有筛选到匹配文档则根据query和update内容插入新的文档

       multi:布尔值  默认false  表示如果有多条符合条件文档则只修改第一条

               如果设置为true 则表示修改所有符合条件文档

    db.class.update({name:'zhangsan1'},{$set:{age:12}})

   ---》此条是错误的,设置后会把当条信息修改为{age:18} db.class.update({name:'zhangsan'},{age:18})

  

    修改所有年龄小于 10为18

    db.class.update({age:{$lt:10}},{$set:{age:18}},false,true)

    $set

      修改一个域的值

      没有这个域的话,自动添加

      db.sanguo.find({name:'liu'})

    $unset 

      删除一个域

       db.class.update({gongji:1000},{$unset:{name:''}})

    $rename

      更改所有域名name,更名为name1

      db.sanguo.update({},{$rename:{name:'name1'}},false,true)

    $setOnInsert

      如果db.collection.update()with upsert:true找到了匹配的文档,那么MongoDB会执行更新,应用$set操作但忽略$setOnInsert操作。

      如果使用update插入了文档,则将该修改器内容作为插入文档的一部分

      db.class1.update({name:'liu'},{$setOnInsert:{age:18}},true)

    $inc 加法修改器

      所有人年龄加1

      db.class1.update({},{$inc:{age:1}},false,true)

    $mul

      乘法修改器,参数可以是正数负数,整数小数

      db.class1.update({},{$mul:{age:2}},false,true)

    $min

      如果筛选文档的指定域值小于min值则不修改,大于min 值则修改为min值

      如果年龄大于20则修改为20

      db.class1.update({name:'刘杰'},{$min:{age:25}})

    $max

      如果筛选文档的指定域值大于max值则不修改,小于max值则修改为max值

      如果年龄小于25则修改为25

      db.class1.update({name:'刘杰'},{$max:{age:25}})

    $push

      向数组中添加一项

      给小黑 score中添加一项91

      db.class.update({name:'小黑'},{$push:{score:91}})

    $pushAll

      向数组中添加多项

       db.class.update({name:'小刚'},{$pushAll:{score:[94,10]}})

      mongo 3.6版本之后没有pushAll,用后面的这句 【db.class.update({name:'小鸡'},{$push:{score:{$each:[9,8]}}}) 】

    $pull

      从数组中删除一项

      db.class.update({name:'小刚'},{$pull:{score:94}})

    $pullAll

      从数组中删除多项

      db.class.update({name:'小刚'},{$pullAll:{score:[90,10]}})

    $each

      对多个值逐个进行操作

        分别插入99.10

      db.class.update({name:'小刚'},{$push:{score:{$each:[99,10]}}})

    $position  

      指定插入位置

      将67插入到数组1号位置

      db.class.update({name:'小明'},{$push:{score:{$each:[67],$position:1}}})

    $sort

      数组排序

      将所有score域的数组降序排序

      db.class.update({},{$push:{score:{$each:[],$sort:-1}}},false,true)

    $pop

      弹出一项  1表示弹出最后一项  -1 弹出第一项

      db.class.update({name:'小刚'},{$pop:{score:-1}})

    $addToSet

      向数组中添加一项,但是不能添加重复的内容

      如果有重复的内容则不添加

      db.class.update({name:'小刚'},{$addToSet:{score:10}})

   

时间数据类型

  mongo中存储时间大多为 ISODate

  存储当前时间方法、  

    1  new Date()  自定义生成当前时间  

      db.class.insert({book:'PYTHON入门',date:new Date()})

    2 ISODate()  自动生成当前时间

      db.class.insert({name:'liu',date:ISODate()})

    3 Date()  将系统时间转换为字符串

      db.class.insert({name:'jie',date:Date()})

  指定时间

    ISODate()

    功能:生成mongodb标准时间类型

    参数:如果不传参默认为当前时间

       传参表示指定时间

        “2018-01-01 12:12:12”

        "20180101 12:12:12"

        "20180101"

    db.class.insert({name:"python崩溃",date:ISODate('2018-01-01 12:12:12')})

  时间戳

    valueOf()

    获取某个时间的时间戳

      db.class.insert({name:"python时间戳",date:ISODate().valueOf()})

Null类型

  值null

  1 如果某个域存在却没有值可以赋值为null

    db.class.insert({name:"python死去活来",price:null})

  2 可以查找某域不存在的情况

    如果date域不存在也能 find 到

    db.class.find({date:null})

Object(内部文档)

  文档内部某个域的值还是一个文档数据则这个文档就是内部文档类型数据

  通常使用外部文档域名,引用内部文档域名的方式使用内部文档

    db.class.find({'book.title':'狂人日记'})

    db.class.find({'book.price':{$gte:48}})

    db.class.update({name:'钱钟书'},{$set:{'book.price':48.8}})  更改

通过数组下标直接操作某一项  

    通过数组下标引用第一项进行查找或更改

    db.class.find({'score.0':{$gt:90}},{_id:0}) 

    db.class.update({name:'小明'},{$set:{'score.1':90}}) 

索引

  指建立指定键值及所在文档存储位置的对照清单,使用索引可以方便我们进行快速查找,减少遍历次数提高查找效率

  ensureIndex()

    功能:创建索引

    参数:索引域和索引选项

    db.sanguo.ensureIndex({name1:1})

    1 正序,,-1 倒序

     * 注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(),之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。 
  查看集合中索引
    db.collection.getIndexes()
  自定义索引名称
    db.collection.ensureIndex({},{name:"myIndex"})
  删除索引
    db.collection.dropIndex('index')
      功能:删除索引
      参数:要删除的索引名称或者键值对
       删除键值对方式: db.sanguo.dropIndex({name1:1})
       删除名称方式 : db.sanguo.dropIndex('ageIndex')
  删除所有索引
    db.collection.dropIndexes()
     功能:删除所有索引
     * _id 是系统自动创建的主键索引,不能删除
  索引类型
    复合索引
      根据多个域创建一个索引
      db.sanguo.ensureIndex({name1:1,age:-1},{name:'name-age'})
    数组索引,子文档索引
      如果对某个域的值为数组或者子文档的域创建索引,那么通过数组或者子文档中某一项进行查找也是索引查找
        如果对score创建了索引那么该查找就是索引查找
          db.class.find({'score.1':88})
    唯一索引【创建索引的域要求值不能够重复】
      对name创建唯一索引
      db.sanguo.ensureIndex({name:1},{unique:true})
    稀疏索引(间隙索引)
      只针对有指定索引域的文档创建索引,没有该域的文档不会插入到索引表
       db.sanguo.ensureIndex({age:1},{sparse:true})
    索引约束
      * 索引表需要占用一定的数据库磁盘空间
      * 当对数据进行增 删 改等写入操作时索引也需要更新,降低了数据性能
      综上 :
        数据量较小时不适合创建索引,当数据库进行频繁的修改操作而不是查找操作时也不适合创建索引。针对一个集合并不是创建索引越多越好。
      
聚合操作
  对文档的筛选结果进行整理统计
    db.collection.aggregate()
      功能:完成聚合操作
      参数:聚合条件 --》聚合操作符
  $group  分组聚合  需要配合具体的分组统计选项
    $sum : 求和
      统计sex 下的男女数量
      db.class.aggregate({$group:{_id:'$sex',num:{$sum:1}}})
      求男女年龄的总和
      db.class.aggregate({$group:{_id:'$sex',num:{$sum:'$age'}}})
    $avg :按性别求年龄平均数
      db.class.aggregate({$group:{_id:"$sex",avg:{$avg:'$age'}}})
    $max :按性别求年龄最大值
      db.class.aggregate({$group:{_id:'$sex',max:{$max:'$age'}}})
    $min: 按性别求年龄最小值
      db.class.aggregate({$group:{_id:'$sex',min:{$min:'$age'}}})
  $project 修改文档的显示效果
      第一种【与 find({},{_id:0})没有区别】:db.class.aggregate({$project:{_id:0,name:1,age:1}})
      第二种【更改显示的字段名称】:db.class.aggregate({$project:{_id:0,name1:'$name',age1:'$age'}})
  $match数据筛选
    $match 值的用法同query一致
      过滤年龄大于18岁的数据文档
      db.class.aggregate({$match:{age:{$gt:18}}})
    $limit 筛选前几条文档
      筛选前三条数据文档
      db.class.aggregate({$limit:3})
    $skip 跳过几条文档显示
      跳过前三条文档
      db.class.aggregate({$skip:3})
    $sort 将数据排序
      按年龄排序   1 是升序  -1 降序
      db.class.aggregate({$sort:{age:1}})
聚合管道
  聚合管道指的是将上一个聚合的操作结果给下一个聚合继续操作
  db.collection.aggregate()  
    找出性别是男,不显示_id,把age按升序排序
    mathc ---> project --> sort
    db.class.aggregate({$match:{sex:'m'}},{$project:{_id:0}},{$sort:{age:1}})
  
    找到重名的学生
    group --> match
    db.class.aggregate({$group:{_id:'$name',num:{$sum:1}}},{$match:{num:{$gt:1}}})
 


固定集合:mongodb中可以创建大小固定的集合
  特点:能够淘汰早期数据(自动)    使用:日志处理
       插入和顺序查找的速度更快    临时缓存
     可以控制集合的空间大小
  创建:
    db.createCollection(collection:{caaped:true,size:10000,max:1000})
    参数:
      capped:true  创建固定集合
      size: 10000   表示指定集合的大小(字节数)
      max 1000  表示最多存多少文档
 
文件存储:
  1 存储路径:将文件放在本地路径(网络路径下),然后数据库中存储该文件的查找路径
    优点:节省数据库空间,操作简单快捷
    缺点:当数据库或文件位置发生变化时,文件会丢失
  2 将文件转为二进制,存储文件本身
    优点:数据库和文件绑定,数据库,文件就在
    缺点:占用空间圈套,存取效率低
  mongodb中,若小文件建议转换二进制直接插入
        若大文件建议使用gridFS方案存储(>16M)  
  GridFS方案:
    在mongodb中以两个集合相互配合的方法来存储文件
      fs.files:用来存储文件相关信息(文件名,文件类型)
        文档结构
          { "_id" : ObjectId("5ba452dc69d72e0d44a54783"),
          "chunkSize" : 261120, "uploadDate" : ISODate("2018-09-21T02:09:33.222Z"),
          "length" : 70989176, "md5" : "1db8b66529191d3c6e6798d2704c75fe",
           "filename" : "ps.exe" }
      fs.chunks:分块存储文件实际内容
          { "_id" : ObjectId("5ba452dc69d72e0d44a547ab"),
            "files_id" : ObjectId("5ba452dc69d72e0d44a54783"),
            "n" : 39, "data" : BinData(0,"a....")}
   在命令行:
      存入文件
      mongofiles -d dbname put file 
         dbname:将文件存入数据库名字,不存在则自动创建
         file:要保存的文件
        (数据库会自动创建两个集合)
      提取文件
      mongonfiles -d dbname get file
       
    GridFS方案
      优点:操作方便,提供较好的存储命令,使用数据库存储文件,方便移植
      缺点:读写文件效率低
游标 cursor
  通过获取操作数据库的返回结果,得到返回结果对象,通过游标可以进一步获取操作结果数据
    var = cursor = db.class.fund()
    cursor.hasNext()  查看是否有下一个对象
    cursor.next()    获取下一条结果
 
通过python操作 MongoDB
   pymongo
    安装 sudo pip3 install pymongo
  操作步骤
    1 import pymongo
      创建mongodb的数据库连接对象
       conn = pymongo.MongoClient()  #此处不填 则表示连接本地数据库,端口为27017
      
import pymongo
conn = pymongo.MongoClient()
db = conn.stu  #连接数据库
myset = db.class1# 定到class1集合
conn.close()
View Code
    2 生成数据库对象
      db = conn. stu
      db = conn['stu']  (通过__setitem__,__getitem__实现的魔法方法)
    3 生成集合对象
      myset = db.class0
      myset = db['class0']
    4 通过集合对象调用操作方法(增删改查,索引,聚合)
      插入操作:
          insert
          insert_many  【用列表】
          save
          insert_one
    
# myset.insert({'name':'张林','age':18})
# myset.insert([{'name':'张国立','king':'康X'},
#              {'nme':'陈道明','king':'康X'}])
# myset.insert_many([{'name':'康国强','king':'雍正'},
#                    {'name':'陈建斌','king':'雍正'}])
# myset.insert_one({'name':'郑少秋','king':'乾隆'})
#myset.save({'_id':1,'name':'聂远','king':'乾隆'})
#c = myset.save({'_id':4,'name':'吴奇隆','king':'四爷'})
View Code

       查找操作

        find()

          功能:查找数据库内容

          参数:同 mongo shell find()

          返回值:返回一个结果游标(需要遍历结果集)

        find_one()

          功能:查询第一条符合条件的文档

          参数:同find()

          返回值:返回一个字典

      操作符的使用

         找出年龄大于18的

          for i in myset.find({'age':{'$gt':18}},{'_id':0}):
            print(i)

         * 在pymongo中所有操作符的用法同mongo shell相同,只是操作时加引号,以字符串的方式写入python代码

          cursor对象的属性

           next()

           limit()

             count()

             sort()

sursor = myset.find({'age':{'$gt':18}},{'_id':0})
sursor.skip(1)
print(sursor.count())
for i in sursor.limit(2):
    print(i)
  
* 使用 for 或者 next 使游标位置不再指向来头位置的时候调用limit skip sort就会报错

sort排序在写法上面有差别
  pymogo :   sursor.sort([('age',1),('name':-1)]
  mongoshell : sort({age:1,name:-1})
sursor = myset.find({'$or':[{'sex':'男'},{'age':{'$gt':16}}]})

       修改操作

         update(query,update,upsert=False,multi=False)

           myset.update({'fangyu':100},{'$unset':{'sex':''}})

           myset.update({'name':''Jame},{'$set':{'age':21}},mullti = True)

          myset.update({'gender':None},{'$set':{'gender':'v'}},multi=True)  【查询空用None】

           同时修改多条文档

            myset.update({'gongji':119},{'$set':{'age':18}},multi = True)

            如果匹配文不存在则插入

            myset.update({'name':'渣渣辉'},{'$set':{'age':18,'sex':'男'}},True)

         update_many()

         update_one()

        

      删除操作

      remove(query,multi = True)

        multi默认是true表示删除所有query过滤文档

        设置为False表示只删除一条

      myset.remove({'score':None}) 【删除没有score域的纪录】

      * python 中 True ==> true

            False ==> false

           None ==> null

      复合操作

        myset.find_one_and_delete({'king':'123'})  【找到一条并删除】

      索引操作

        ensure_index()

          index = myset.ensure_index('name')

        list_indexes()  #查看所有索引

          myset.list_indexes()

        drop_index()

          index = myset.ensure_index('name')#增加name索引

          print(index)  #索引名为name_1

          myset.drop_index('name_1')

        drop_indexes()

        

#index = myset.ensure_index('name')#增加name索引
#index = myset.ensure_index([('age',-1,)])#增加age索引
# myset.drop_indexes()#删除所有的索引
# for i in myset.list_indexes():#查看所有索引
#     print(i)

      复合索引:

          index = myset.ensure_index([('name',1),('age',-1)])

      唯一索引

          myset.ensure_index('name',name='Myindex',unique=True)

      稀疏索引

          myset.ensure_index('name',sparse = True)

    聚合操作

      aggregate([])

      参数:和mongo shell一样

      返回值:返回和find()函数相同的游标对象

        

p = [{'$group':{'_id':'$country','num':{'$sum':1}}},
     {'$match':{'num':{'$gt':1}}}]
 for i in myset.aggregate(p):
    print(i)

__________

cursor = myset.aggregate(
[
{'$match':{'sex':'m'}},
{'$project':{'_id':0,'name':1,'score.chinese':1}}
]
)

    读文件以grid方案存放到数据库

      * 小文件存储方案

        直接转换为二进制格式插入到数据库

      存储小文件

        import bson

        bson.binary.Binary()

          功能:将bytes格式子串转换为mongodb的二进制存储格式

      

import pymongo
conn = pymongo.MongoClient()
import bson
db = conn.image
myset = db.mm
# f = open('1.png','rb')#写入开始
# content = bson.binary.Binary(f.read())
# #插入到文档
# myset.insert({'date':content,'name':'1.png'})#写入结束

# img= myset.find_one({'name':'1.png'})#查找开始
# with open('1.png','wb') as f:
#     f.write(img['date'])#查找结束
conn.close()
View Code---小文件存储方案
import gridfs
conn = pymongo.MongoClient()
db = conn.grid
fs = gridfs.GridFS(db) #获取gridfs对象
# with open('text1.py','rb') as f:
#     fs.put(f.read(),filename='text1.py')#存入文件到数据库二进制

files = fs.find()#分别取每一个文件
for i in files:
    print(i.filename) #打印每个文件名称
    if i.filename == 'text1.py':
        with open('text1.py','wb') as f:
            f.write(i.read()) #从数据库读出来并写到 f

conn.close()
View Code---大文件存储和取出方案
    5 关闭数据库连接
      conn.close()
  
   
原文地址:https://www.cnblogs.com/Skyda/p/9670671.html