zoukankan      html  css  js  c++  java
  • 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()
      
       
  • 相关阅读:
    前端CSS部分知识整理
    css随笔记(持续更新)
    前端样式脚本本地化开发
    样式脚本本地化开发方法①【前端开发技巧】
    微信公众号吸粉简易新策略(自整理持续待更新)
    Wave
    无聊时百度了一下自己的名字。吓到我了
    Java实现 LeetCode 819 最常见的单词(暴力)
    Java实现 LeetCode 819 最常见的单词(暴力)
    Java实现 LeetCode 823 带因子的二叉树(DP)
  • 原文地址:https://www.cnblogs.com/Skyda/p/9670671.html
Copyright © 2011-2022 走看看