python_MongoDB

爷,独闯天下 提交于 2020-10-31 02:00:34

数据库 MongoDB
数据存储的发展阶段
    1、文件管理阶段(open,csv,)
        1、优点:数据可以长期保存,能存储大量的数据,使用比较简单
        2、缺点:数据的一致性差,数据冗余度大,查找修改不方便
    2、数据库管理阶段
        1、优点:数据组织结构化,冗余度小,容易扩充,查找效率高,方便使用程序自动处理
        2、缺点:需要使用sql语句等特定的语句处理,相对比较复杂
几个概念:
    1、数据:能够输入到计算机中被识别处理的信息集合
    2、数据库:按照数据结构,存储和管理数据的仓库。是在数据库管理系统的管理和控制下存放在一定介质上的数据集合
    3、数据库管理系统:管理数据库的软件,用于建立,使用和维护数据库
    4、数据库系统:由数据库,数据库管理系统,开发工具等共同构成的集合概念
关系型数据库:
    1、定义:采用关系模型来组织数据结构的数据库
    2、关系型数据库包括:Oracle DB2 SQLServer MySql  SqLite(小型数据库,方便一致,python标准库支持)
    3、优点:
        1、容易理解,类似我们常见的表格模型
        2、使用方便,都是通过sql语句进行操作,sql语句是非常成熟的
        3、易于维护,完整性好,数据一致性高,降低了冗余
        4、技术成熟,可以使用外连接等比较复杂的操作
    4、缺点:
        1、不能很好的满足高并发的需求,每次操作需要sql语句,sql语句需要解析
        2、针对海量数据的瞬间爆发在读写性能上显得不足,关系型数据库内部每一步操作为了保证原子性都会加锁
        3、数据一致性较高,在处理某些数据情况时浪费资源
        4、数据库扩展比非关系型数据库要复杂困难
非关系型数据库(NoSQL:Not only sql):
    1、定义:
    1、优点:
        1、高并发,大数据下读写能力强
        2、支持分布式,容易扩展
        3、弱化了数据结构,降低了数据的一致性
    2、缺点:
        1、没有join等复杂的操作
        2、通用性差(不同的nosql数据库有不同的使用方法)
        3、操作灵活但是容易混乱
面试要求:能够描述关系型和非关系型数据库的特点
Nosql的使用情况:
    1、数据模型简单灵活,一致性差
    2、对数据库的并发处理要求高
    3、数据库设计时无法准确估量大小,后期可能需要扩展
    4、给定的数据关系比较容易建立起键值模型
NoSQL的分类:
    1、键值型数据库:Redis、oracle BDB 、Tokyo
    2、列存储数据库:HBase
    3、文档型数据库:MongoDB、CouchDB
    4、图形数据库:
要求:知道Nosql数据库分为几类,MongoDB是文档型数据库
MongoDB:
    1、是一个文档型非关系数据库
    2、由C++编写的数据库
    3、支持丰富的查询操作
    4、支持众多编程语言的接口(python ruby c++ c#  PHP)
    5、使用简单,便于部署
    6、数据格式丰富
    7、支持分布式扩展
安装:
    1、自动安装:sudo apt-get install mongodb(默认安装位置/var/lib/mongodb,配置文件/etc/mongodb.conf,命令集/usr/bin)
    2、手动安装:
        1、下载对应系统的安装系统
        www.mongodb.com --->download--->community server
        2、选择安装目录(/usr/local/ 或者  /opt),选择一个位置将安装解压包 tar
        3、进入解压后的文件,将bin目录添加到环境变量
            1、PATH=$PATH:/usr/test/mongodb/bin/
            2、export PATH
            3、将这两句添加到linux自动执行脚本/etc/rc.local  或者 etc/bash.basehrc 或者 其他自启动脚本
            4、重启系统  source /etc/basehrc    或者reboot
        4、设置数据库的存储位置:
            1、sudo mkdir -p  /data/db
            2、mongod --dbpath db
mongodb的shell命令
    1、mongodb --port 8888:设置mongodb的端口号(默认端口号为27017)
    2、mongo :mongo shell 表示进入到mongodb的交互模式,支持JavaScript语言
    3、quit():退出MongoDB shell
数据类型:
    1、字符串
    2、整型
        1、整数,32位整型
    3、布尔型
        1、true false
    4、浮点型
        1、存储小数
    5、数组类型(列表)
        1、列表数组
    6、时间类型
        1、Date 时间日期
    7、文档类型(内部文档)
        1、Object
    8、空值null
    9、字符串
        1、symbol通常表示特殊字符
    10、时间戳
        1、Timestamp 时间戳
    11、ObjectID
        1、object字串:ObjectId("5b61190098fd02be2bb47755")
        2、系统自动为每个文档生成的不重复的主键,键(_id)值(ObjectId("5b61190098fd02be2bb47755"))
        3、24位十六集进制数,前8位文档创建时间,6位机器ID ,4位进程ID,6位计数器
    12、二进制
        1、Binary data
    13、代码(js代码)
        1、code
    14、正则表达式
        1、regex
MongoDB存储数据的一些概念:
    MySql            MongoDB                 含义
    database        database                数据库
    table            collection                表/集合
    column            field                    字段/域
    row                document                记录/文档
    index            index                    索引
创建数据库:
    1、use databasename
        比如 use stu:创建一个叫stu的数据库。
        说明:use实际的功能表示使用哪个数据库,如果选择一个不存在的数据库则当向数据库插入数据时该数据库会自动创建
    2、show dbs :查看当前数据库系统中的数据库
数据库的命名规则:
    1、原则上是满足一下几条的任意utf-8格式的字符串
    2、不能是空字符
    3、不能含有空格,点,/  \  \0(c++中表示结尾)
    4、习惯上全部小写
    5、长度上不应超过64字节
    6、不能使用admin local config 这三个名字
        1、admin:存储用户权限
        2、local:不会被赋值,只能用于本机操作
        3、config:分片处理时存储分片信息
db :一个数据库全局量,代表你当前正在使用的数据库,默认表示test数据库

数据库的备份和恢复
    备份:mongodump    -h dbhost -d dbname -o dir
        示例:mongodump -h 127.0.0.1 -dstu -o /home/xdl/mydata:将本机stu数据库备份到/home/xdl/mydata文件夹下
    恢复:mongorestore -h <hostname>:<port> -d dbname  <path>
        示例:mongorestore -h 127.0.0.1:27017 -d test /home/xdl/mydata/stu
数据库的检测:
    mongostat
        insert(每秒插入次数) query(每秒查询次数) update(每秒更新次数) delete(每秒删除次数) getmore command(每秒运行命令次数) dirty used flushes(每秒向磁盘写入次数) vsize(使用虚拟内存情况)   res(使用物理内存情况) qrw arw net_in net_out conn   time  
    mongotop 检测每个数据库的读写时长
        ns(数据表)   total(总时长)    read(读时长)    write(写时长)
删除数据库
    db.dropDatabase()

创建集合:
    方法1:db.createCollection(collection_name)
    方法2:db.collection_name.insert({}):当向一个集合中插入一条文档,如果这个集合不存在时,则会自动创建
        示例:db.class2.insert({name:'Lily',age:17,sex:'w'}):会自动创建class2这个集合
    方法3:db.collection_name.save({})
查看数据库中的集合:
    show tables 或 show collections
集合的命名规则:
    1、不能是空字符串
    2、不能含有‘\0’
    3、不能以system.开头,这是系统集合的保留前缀
    4、集合不要和保留字重名,不要包含$
删除集合:
    db.collection_name.drop()
    示例:db.stu.drop():删除stu这个集合

文档:
    1、在MongoDB中数据的组建形式,由键值组成,类似于python中的字典
    2、mongodb中的数据文档为bson格式(类似于python字典,使用键值的方式保存和展示数据)
文档中键的命名规则:
    1、utf-8格式的字符串
    2、不能有\0,不能为空(习惯上不用.和$)
    3、以_开头的很多都是保留的键,所以一般不用_开头
    4、注意:
        1、文档中的键值对是有序的
        2、文档中的值指的就是文档支持的数据类型
        3、mongodb中区分大小写
        4、键不能重复,重复的时候后面的会把前面的覆盖掉

        比如:db.book.insert({java:1,java:2})      { "_id" : ObjectId("5d20516bb6893bdbe138360f"), "java" : 2 }
集合设计原则:
    1、同一类文档存在一个集合中
    2、集合中尽量存储域和文档格式相近的文档
    3、集合中可以存在文档数据的差异

插入文档:
    1、insert插入数据
        1、插入一条文档:db.collection_name.insert({})
            示例:db.class1.insert({name:'刘能',age:22,sex:'m'})
            说明:插入文档时域名可以加引号也可以不加引号
        2、插入多条文档:db.collection_name.insert([{},{},...])
        3、说明:_id为系统定义的主键值,如果使用系统值则保证不重复,如果自定义值即会覆盖系统值,但是自己也不能让该域重复
    2、save插入数据:
        1、db.collection_name.save()
        2、如果不添加_id域的时候同insert
        3、如果添加_id域,该域如果不存在则正常插入,如果存在则修改原来数据
        4、无法插入多条文档,(有待验证)
    3、db.集合名 等价于 db.getCollection(集合名)
修改集合名称:
    1、 db.collection_name.renameCollection(集合名)
        示例:db.class1.renameCollection('class0')

查找:
    1、db.collection_name.find(query,field)
        1、功能:查找所有符合筛选要求的文档
        2、参数:
            1、query:筛选条件
                示例:
                    1、db.class0.find({age:22},{_id:0})
                说明:
                    1、以键值的方式确定查找条件
                    2、如果不写该参数,则表示查找所有文档

            2、field:展示的域 ,0表示展示该域,1表示不展示该域
                示例:
                    1、db.class0.find({},{_id:0})
                    2、db.class0.find({},{_id:1})
                说明:
                    1、以键值对的形式给每个域赋值0,1表示时候要显示该域
                    2、如果给域设置为0,其他域自动为1,如果给某个域设置为1,则其他自动为0,两者不能混用
                    3、_id比较特殊,默认为1,如果不想显示则设置为0,_id为0时其他的是可以为1的
                    4、如果不写该参数,则表示显示所有的域
        3、返回值:返回所有符合要求的文档
    2、db.collection_name.findOne()
        1、功能:查找符合条件的第一条文档
        2、参数:同find
        3、返回值:返回查找的文档
        4、实例:db.class0.findOne({age:22},{_id:0})
    3、query的更多用法:
        1、比较运算符:
            1、$eq:等于
                1、示例:db.class0.find({age:{$eq:22}},{_id:0})
            2、$lt:小于
                1、示例:
                    1、db.class0.find({age:{$lt:22}},{_id:0})
                    2、db.class0.find({name:{$lt:'张三'}},{_id:0})#根据汉子的转码比较大小
            3、$lte:小于等于
                1、示例: db.class0.find({age:{$lte:22}},{_id:0})
            4、$gt:大于
                1、示例: db.class0.find({age:{$gt:22}},{_id:0})
            5、$gte:大于等于
                1、示例:db.class0.find({age:{$gte:22}},{_id:0})
            6、$ne:不等于
                1、示例:db.class0.find({age:{$ne:22}},{_id:0})
                2、说明:如果某个文档没有age这个域也会显示为不等于22
            7、$in:包含
                1、示例:db.class0.find({age:{$in:[22,23,24]}},{_id:0})
            8、$nin:不包含
                1、示例:db.class0.find({age:{$nin:[22,23,24]}},{_id:0})
            9、说明:
                1、比较运算符也是键值的方式,给比较运算符设置一个值,表示相应的关系
                2、在mongodb中字符串也可以比较大小
        2、逻辑运算符:
            1、$and:逻辑与
                1、示例:
                    1、db.class0.find({age:22,sex:'m'},{_id:0})
                    2、db.class0.find({$and:[{age:22},{sex:'m'}]},{_id:0})
                    3、db.class0.find({age:{$gt:22,$lt:25}},{_id:0})#年龄在22与25之间的(不包括22和25)
                2、说明:
                    1、默认在query中逗号分割的多个条件即为逻辑与关系
            2、$or:逻辑或
                1、实例:
                    1、db.class0.find({$or:[{age:22},{sex:'w'}]},{_id:0})
                    2、db.class0.find({$or:[{age:{$lt:23}},{age:{$gt:25}}]},{_id:0})
            3、$not:逻辑非
                1、示例: db.class0.find({age:{$not:{$eq:22}}},{_id:0})
            4、$nor:既不也不(集合中的条件都不满足的文档)
                1、示例:db.class0.find({$nor:[{age:18},{sex:'m'}]},{_id:0})
            5、条件混合:
                1、示例:
                    1、db.class0.find({$or:[{age:{$lt:20}},{name:'阿荣',sex:'w'}]},{_id:0})#年龄小于20或者(名字为‘阿荣’并且性别为女)
                    2、db.class0.find({$or:[{age:{$lt:20}},{name:'阿荣'}],sex:'w'},{_id:0})#年龄小于20或者名字为‘阿荣’并且性别为女
    数组查找:
        1、示例:db.class1.find({hobby:'Python'},{_id:0})#查看hobby数组中含有Ptthon的文档
        2、$all:查看数组中包含多项的文档
            示例:db.class1.find({hobby:{$all:['Python','Game']}},{_id:0})
        3、$size:查看数组中项数为指定个数的文档
            示例:db.class1.find({hobby:{$size:3}},{_id:0})
        4、$slice:查看数组中的前几项
            示例:
                1、db.class1.find({},{_id:0,hobby:{$slice:1}})
                2、db.class1.find({},{_id:0,hobby:{$slice:[1,2]}})#表示跳过第一项显示后面两项,从下标1开始往后显示2个长度
    其他查找方法:
        1、$exists:判断一个域是否存在
            1、示例:
                1、db.class0.find({sex:{$exists:true}},{_id:0})#查找存在sex域的文档
                2、db.class0.find({sex:{$exists:false}},{_id:0})#查找不存在sex域的文档
        2、$mod:通过整除余数进行查找
            1、db.class0.find({age:{$mod:[3,0]}},{_id:0})#表示年龄被3除余数为0的文档
        3、$type:查找值为指定数据类型的文档
            1、db.class0.find({age:{$type:1}},{_id:0})

     $type的值可以是数据类型值或者数据类型的对应的编号:https://blog.csdn.net/user_longling/article/details/80565981
和查询结果相关的几个函数:
    1、distinct():查看一个集合中某个域的值所覆盖的范围
        示例:
            1、db.class0.distinct('age')
            2、db.class1.distinct('hobby')#查看列表域时是将列表求并集
    2、pretty():将查询结果格式化显示
        示例:db.class0.find({}).pretty()
    3、limit(n):查询结果显示前n个文档,默认为全部显示
        示例:db.class0.find({},{_id:0}).limit(3)
    4、skip(n):跳过前n条文档显示,默认不跳过
        示例:db.class0.find({},{_id:0}).skip(2)
    5、count():对查询结果进行计数
        示例:db.class0.find({},{_id:0}).count()
    6、sort({}):
        1、功能:按照指定的字段进行排序
        2、参数:键值对,某个域按照升序排序值为1,降序排序则为-1
        3、说明:空值为最小的
        示例:
            1、db.class0.find({},{_id:0}).sort({age:1})#升序
            2、db.class0.find({},{_id:0}).sort({age:-1})#降序
            3、db.class0.find({},{_id:0}).sort({age:1,name:-1})#当age相同时按照name排序
    7、函数的联合使用:
        1、示例:
            1、db.class0.find({},{_id:0}).sort({age:1}).limit(3)
            2、 db.class0.find({},{_id:0}).sort({age:1}).limit(3).count()#结果并不是3
删除文档:
    db.collection_name.remove(query,justOne)
        1、功能:删除文档
        2、参数
            1、query:定位要删除的文档数据,类似sql where子句,用法和查找相同
            2、justOne:给bool值,默认为False表示删除所有符合条件的数据文档,如果为true则表示只删除第一条符合条件的文档
            3、示例:
                1、db.class0.remove({sex:{$exists:false}})#删除所有不含sex域的文档
                2、db.class0.remove({age:22},true)#删除年龄为22的第一条文档
    db.collection_name.remove({}):删除集合中所有的文档,{}不可省略


练习:
    1、创建一个数据库名字为gread
        use gread
    2、数据库中创建集合名字为class
        db.createCollection('calss')
    3、集合中插入若干文档,文档格式为:{name:'小红',age:10,sex:'w',hobby:["a",'b',c]}
        db.class.insert({name:'小红',age:5,sex:'w',hobby:['画画']})
        db.class.insert({name:'小花',age:4,sex:'w',hobby:['画画','跳舞','唱歌']})
        db.class.insert({name:'小明',age:7,sex:'m',hobby:['打球','跳舞','唱歌']})
        db.class.insert({name:'小强',age:9,sex:'m',hobby:['打球','打游戏','唱歌','看电视']})
        db.class.insert({name:'李华',age:10,sex:'m',hobby:['打球','学习']})
    4、查看该班所有学生信息
        db.class.find({},{_id:0})
    5、查看年龄为5岁学生的信息
        db.class.find({age:5},{_id:0})
    6、查看年龄大于6岁的学生信息
        db.class.find({age:{$gt:6}},{_id:0})
    7、查看年龄在4--8之间的学生
        db.class.find({$and:[{age:{$gt:4}},{age:{$lt:8}}]},{_id:0})
        db.class.find({age:{$gt:4,$lt:8}},{_id:0})
    8、查看年龄大于4岁并且为男生的学生
        db.class.find({age:{$gt:4},sex:'m'},{_id:0})
    9、查看年龄小于4或者大于8的学生
         db.class.find({$or:[{age:{$lt:4}},{age:{$gt:8}}]},{_id:0})
    10、查看兴趣爱好有2项的学生
        db.class.find({hobby:{$size:2}},{_id:0})
    11、查看兴趣有画画的学生
         db.class.find({hobby:'画画'},{_id:0})
    12、查看兴趣既有花花又有跳舞的学生
        db.class.find({hobby:{$all:['画画','跳舞']}},{_id:0})
    13、查看兴趣有三项的学生的人数
         db.class.find({hobby:{$size:3}},{_id:0}).count()
    14、查看本班年龄第二大的学生
         db.class.find({},{_id:0}).sort({age:-1}).skip(1).limit(1)
    15、将学生年龄按照升序,姓名按照降序排列
        db.class.find({},{_id:0}).sort({age:1,name:-1})
    16、统计学生的兴趣范围
        db.class.distinct('hobby')
    17、删除所有年龄小于4的男生
        db.class.remove({age:{$lt:4},sex:'w'})

更新文档:
    db.collection_name.update(query,update,upsert,multi)
        1、功能:更新一个文档数据
        2、参数:
            1、query:定位要更新的数据,相当于where,用法同查找
            2、update:将数据更新为什么,相当于set,需要配合修改器操作符来使用
            3、upsert:bool值,默认为false表示当定位的文档不存在则无法修改,如果设置为True,表示如果定位不存在则插入这条文档
            3、multi:bool值,默认为false表示如果query匹配的文档有多条则只更新一条,如果为True则修改所有匹配到的文档
        3、实例:
            1、db.class0.update({name:'阿花'},{$set:{age:19}})
            2、db.class0.update({name:'阿哲'},{$set:{age:19}},true)#阿哲这个域不存在,则将添加这条文档
            3、db.class0.update({age:22},{$set:{age:10}},true,true)#修改所有匹配到的文档
    修改器:将数据修改为什么
        1、$set:修改一个值,同时有增加一个域的作用
            示例:
                1、db.class0.update({name:'阿花'},{$set:{age:21,sex:'m'}})
        2、$unset:删除一个域
            示例:db.class0.update({name:'阿哲'},{$unset:{sex:'m'}})
        3、$rename:
            示例:db.class0.update({},{$rename:{sex:'gender'}},false,true)#将所有文档中sex域名修改为gender,新域名需要加引号
        4、$inc:对某个域的值进行加减修改
            示例:
                1、db.class0.update({name:'宝强'},{$inc:{age:1}})#年龄在原有的基础上增加1
                2、db.class0.update({name:'宝强'},{$inc:{age:-2}})#年龄在原有的基础上减少1
        5、$mul:对某个域的值进行乘法修改
            示例:
                1、db.class0.update({name:'宝强'},{$mul:{age:2}})
                2、db.class0.update({name:'宝强'},{$mul:{age:0.5}})
        6、$min:设置最小值,如果query到的文档指定域的值小于 min设定的值则不做修改,如果大于min设置的值则修改为min值
            1、示例:db.class0.update({name:'宝强'},{$min:{age:1}})#如果原来的age小于1则不修改,如果大于1或者该域不存在则修改为1
        7、$max:设定最大值,与$min的用法相反
            1、示例:db.class0.update({name:'宝强'},{$max:{age:7}})#如果原来的age大于7则不修改,如果小于7或者该域不存在则修改为7
        8、修改器可以一起使用
            示例:db.class0.update({name:'阿花'},{$inc:{age:1},$set:{gender:'w'}})#年龄加1,gender改为‘w’
    数组修改器:
        1、$push:向列表中添加数据
            示例:db.class1.update({name:'Lucy'},{$push:{hobby:'computer'}})
        2、$pushAll:向列表添加多条数据
            示例:不能使用
        3、$each:配合$push一起使用,向列表张添加多条记录
            示例:db.class1.update({name:'Lucy'},{$push:{hobby:{$each:['python','html']}}})
        4、$pull:从数组中删除数据
            示例:db.class1.update({name:'Lucy'},{$pull:{hobby:'python'}})
        5、$pullAll:从数组中删除多个元素
            示例:db.class1.update({name:'Lucy'},{$pullAll:{hobby:['computer','draw']}})
        6、$pop:从数组的两端弹出数据
            示例
                1、db.class1.update({name:'Jame'},{$pop:{hobby:1}})#弹出最后一个数据
                2、db.class1.update({name:'Jame'},{$pop:{hobby:-1}})#弹出第一项数据
        7、$addToSet:向数组中添加一个元素,该元素不能和其他元素相同
            示例:db.class1.update({name:'Lily'},{$addToSet:{hobby:'gongfu'}})#如果元数组中有‘gongfu’则不会添加

null:
    1、某个域如果没有值,却存在可以设置为null
    2、表示某个域不存在也能够匹配出来

文档类型数据:文档的值为文档类型,类似于python中的字典套字典
    1、外部文档的域引用内部文档的域通过.的方法逐层引用,在使用时需要加引号
        示例:db.book.find({'python.title':'python'})

数组数据的下标引用:使用数组的域.引用下标的方式可以表示数组中某一个住
        示例:db.class1.find({'hobby.0':'song'})

文档有序性的体现:通过[]的方式可以取得查询结果的第几项文档
    示例: db.class1.find()[0]

练习:
    1、db.class.update({name:'小红'},{$set:{age:8,hobby:['画画','跳舞']}})
    2、db.class.update({name:'小明'},{$push:{hobby:'画画'}})
    3、db.class.update({name:'李华'},{$push:{hobby:{$each:['吹牛','打篮球']}}})
    4、db.class.update({name:'小强'},{$addToSet:{hobby:{$each:['跑步','唱歌']}}})
    5、db.class.update({sex:'m'},{$inc:{age:1}},false,true)
    6、db.class.update({name:'小明'},{$unset:{sex:1}})
    7、db.class.update({name:'小明'},{$pop:{hobby:-1}})
    8、db.class.update({name:'小红'},{$pull:{hobby:'画画'}})

索引:
    1、指的是建立指定键值及所在文档中的存储位置的对照关系清单,
    2、使用索引可以方便我们快速查找,减少遍历次数,提高效率
创建索引:
    1、ensureIndex()
        1、功能:创建索引
        2、参数:提供索引的类别选项
            1、
    1、db.class0.ensureIndex({'name':1})#根据name域创建索引,1表示为该域创建正向索引,-1表示逆向索引
    2、db.class0.getIndexes()#查看当前集合的索引,系统自动为_id创建了索引
创建符合索引:
    1、db.class1.ensureIndex({name:1,age:1})
删除索引:db.collection_name.dropIndex()
    1、说明:_id索引不能删除
    2、db.class1.dropIndex({name:1,age:1})
删除所有索引:
    1、db.collection_name.dropIndexes()#删除除_id外的所有索引

explain():
    1、功能:显示详细的查找操作信息
    2、示例:db.class0.find({name:'阿荣'},{_id:0}).explain()

索引类型:
    1、数组索引:如果对某个数组域创建索引,则对数组中的每个值均创建了索引,通过数据中单个值查询也会提高效率
    2、子文档索引:如果某个域,值为文档,对其子文档创建索引,则加快通过子文档进行查找的查找速度
        示例:db.book.ensureInddex({'python.title':1})
    3、唯一索引:唯一索引时,希望创建索引的域有不同的值,也可以通过这个方法来限制域的值
        示例:db.class0.ensureIndex({name:1},{'unique':true})
        说明:创建索引时指定域的值不能重复,创建后插入也不能插入重复的值
    4、覆盖索引:查找时,只获取索引项的内容,而不去连接其他文档内容,这样从索引表就可以得到查询结果,提高了查询效率
        示例:db.class0.find({name:'宝强'},{_id:0,name:1})
    5、稀疏索引(间隙索引):只针对有指定域的文档创建索引表,没有该域的文档不插入到索引列表
        示例:db.class0.ensureIndex({gender:1},{sparse:true})
    6、文本索引:使用文本索引可以快速进行文本索引,这在较长的字符串搜索中比较有用(不支持中文)
        1、创建文本索引
            db.class2.ensureIndex({msg:'text',description:'text'})#创建文本索引
        2、通过单词进行索引搜索(多个单词用空格隔开,如果有其中任意一个单词就会被搜索)
            db.class2.find({$text:{$search:'old new'}},{_id:0})
        3、所有包含空格的语句,要用转义字符
            db.class2.find({$text:{$search:'\'this is\''}},{_id:0})
        4、搜索某个单词,并且不包含某个单词
            db.class2.find({$text:{$search:'city -big'}},{_id:0})#包含city不包含big
        5、删除文本索引:
            1、通过getIndexes()查看索引名称
                db.class2.getIndexes() #"name" : "msg_text_description_text"
            2、通过dropIndex()删除索引
                db.class2.dropIndex("msg_text_description_text")
索引约束:
    1、影响插入,删除,修改数据的效率。当数据发生修改时,索引必须同步更新
    2、索引也占有一定的空间,所以当数据量比较小时不适宜创建索引
    3、综上,并不是所有情况下都适合创建索引或者创建大量索引

固定集合:
    1、MongoDB中可以创建大小固定的集合,称之为固定集合,固定集合性能出色,且适合于很多场景,比如:日志处理、临时缓存
    2、特点:插入数据快,顺序查询速度快,能够淘汰早期的数据
创建固定集合:
    db.reateCollection(collection_name,{capped:true,size:1000,max:1000})
        1、size:表示设置的固定集合的大小 单位(kb)
        2、max:表示固定集合中最多存放多少条文档
    示例:db.createCollection('log',{capped:true,size:1000,max:3})

聚合:对数据文档进行整理统计
    db.collection_name.aggregate(聚合条件)
        1、功能:聚合函数,配合聚合条件进行数据整理

聚合操作符:
    1、$group:分组,按照什么分组由具体的分组操作符而定
        1、$sum:求和
            示例:
                1、db.class0.aggregate({$group:{_id:'$gender',  num:{$sum:1}}})#文档条数求和
                            聚合统计      分组     按照哪个域分组  统计结果域名
                2、db.class0.aggregate({$group:{_id:'$gender',num:{$sum:'$age'}}})#年龄求和
        2、$avg:求平均
            示例:1、db.class0.aggregate({$group:{_id:'$gender',num:{$avg:'$age'}}})
        3、$min:求最小值
            示例:db.class0.aggregate({$group:{_id:'$gender',num:{$min:'$age'}}})
        4、$max:求最大最
            示例:db.class0.aggregate({$group:{_id:'$gender',num:{$max:'$age'}}})
        5、$first:第一个文档的指定值
            示例:db.class0.aggregate({$group:{_id:'$gender',num:{$first:'$name'}}})
        6、$last:最后一个文档的指定值
            示例:db.class0.aggregate({$group:{_id:'$gender',num:{$last:'$name'}}})
    2、$project 用于修饰文档的显示结构,值同find的第二个参数相同
        示例:
            1、db.class0.aggregate({$project:{_id:0,name:1,age:1}})
            2、db.class0.aggregate({$project:{_id:0,NAme:'$name',age:"$age"}})#改变显示的域名
    3、$match:过滤数据,值和query相同
        示例:db.class0.aggregate({$match:{age:10}})
    4、$limit:显示前几条数据,值为一个整数
        示例:db.class0.aggregate({$limit:3})
    5、$skip:跳过几条数据,显示后面的内容
        示例:db.class0.aggregate({$skip:3})
    6、$sort:排序
        示例:
            1、db.class0.aggregate({$sort:{age:1}})#升序
            2、db.class0.aggregate({$sort:{age:-1}})#降序
聚合管道:前一个聚合操作的结果给后一个聚合操作执行
    1、格式:将多个聚合操作放到一个[]中
    2、示例:db.class0.aggregate([{$match:{gender:'m'}},{$sort:{age:1}},{$project:{_id:0}}])

练习:
    1、按照性别进行分组,统计每一组人数
        db.class.aggregate({$group:{_id:'$sex',num:{$sum:1}}})
    2、按照姓名分组,过滤出重命名的同学
        db.class.aggregate([{$group:{_id:'$name',num:{$sum:1}}},{$match:{num:{$gt:1}}}])
    3、统计每名男生的语文分数
        db.class.aggregate([{$match:{sex:'m'}},{$project:{_id:0,name:1,'source.chinese':1}}])
    4、将女生按照英语分数降序排列
         db.class.aggregate([{$match:{sex:'w'}},{$sort:{'soruce.English':-1}}])


文件的数据库存储:
    1、在数据库中以字符串的方式存储文件在本地的路径
        1、优点:节省数据库空间
        2、缺点:当数据库或这文件位置发生变化时即找不到文件
    2、将文件以二进制数据的方式存储在数据库中
        1、优点:文件和数据库绑定
        2、缺点:当存储文件大时,空间使用大,提取困难
    3、GridFs(大文件存储):是MongoDB当中存储大文件的一种方案,MongoDB中认为超过16M的文件为大文件
        1、将文件存储在MongoDB数据库中,通过两个集合共同完成该文件的存储
            1、fs.files:存储文件的相关信息。比如:文件名filename,文件类型content_type等
            2、fs.chunks:实际存储文件内容,以二进制方式分块存储,将大文件分成多个小块,每一小块占一个文档
        2、格式:mongofiles -d dbname put filename
            1、dbname:文件要存储的数据库,如果不存在则自动创建
            2、filename:要存储的文件
        3、示例:mongofiles -d grid put /home/xdl/python/pbase/day16/day16.txt
        4、查看具体文件信息:db.fs.files.find()
        5、查看具体文件内容:db.fs.chunks.find()
            1、_id
            2、files_id:fs.chunks的files_id域的值对应文件在fs.files集合中的文档_id域的值
            3、n:分块信息,文件太小分块为0
            4、data:具体文件内容
        6、优点:存储方便,没有文件个数限制,方便一直
        7、缺点:读写效率低,只能整体修改不能分块更新
游标:
    1、为什么使用游标
        1、防止网络拥塞,造成数据传输慢
        2、避免用户解析带来的体验差,可以进行后端解析
    2、使用方法:
        1、var cursor = db.class0.find()#创建游标
        2、cursor.hasNext()#查看是否有下一条文档
        3、 cursor.next()#获取下一条文档内容

通过python操作MongoDB数据库:
    数据库操作接口:pymongo
    安装:sudo pip3 install pymongo
    增加:
        1、insert()
        2、insert_many()
        3、insert_one()
        4、save()
    删除:
        1、remove()
            1、功能:删除一个文档
            2、参数:可以通过query条件删除,也可以通过文档的_id值进行删除
            3、示例:data = cls.find_one(dic)
                    cls.remove(data['_id'])
    查找:
        1、find()
            1、功能:查找数据库内容
            2、参数:同mongodb中find函数参数,需要符合python语法
            3、返回值:可迭代的游标对象,通过for循环的方式取值
            4、游标对象的属性函数
                1、next():取下一个文档
                2、limit():显示多少条文档
                3、skip():跳过多少条文档
                4、sort():排序
                5、count():统计
        2、find_one()
            1、用法同find(),返回值为查找到的一个文档转变的字典
        3、说明:在python中支持MongoDB中所有的操作符,只是在使用的时候需要通过引号变为字符串的形式
    修改:
        1、update():同Mongo shell中的update操作
        2、update_many():当匹配多个文档是全部修改
        3、update_one():只能修改匹配到的第一个文档
    索引:
        1、创建索引:
            1、create_index()
            2、ensure_index()
        2、删除索引:
            1、drop_index(索引名称)
                1、功能:删除一个索引
                2、参数:索引名称
            2、drop_indexes()
                1、功能:删除指定集合中所有索引

from pymongo import MongoClient
import pymongo

#1、创建MongoDB的连接对象
conn = MongoClient('localhost',27017)

#2、选择要连接的数据库
#db = conn.stu
db = conn['stu']

#3、选择要连接的集合
#my_set = db.class0
my_set = db['class3']
# print(my_set) 
# print(dir(my_set))

#插入数据:
# my_set.insert({'name':'张铁林','King':'乾隆'})#插入一条
# my_set.insert([{'name':'陈道明','King':'康熙'},{'name':'张国立','King':'康熙'}])#插入多条
# my_set.insert_many([{'name':'陈道明','King':'康熙'}])#参数必须是一个列表
# my_set.insert_one({'name':'唐国强','King':'雍正'})#只能插入一条
# my_set.save({'name':'陈建斌','King':'雍正'})#只能插入一条数据

#删除操作
#my_set.remove({'name':'张铁林'})#删除匹配到的所有数据
#my_set.remove({'name':'陈道明'},multi=False)#删除匹配到的第一条数据
#my_set.remove({})#删除所有数据{}可以省略

#查找
cursor = my_set.find()#cursor是一个可迭代对象
# for i in cursor:
#     print(i['name'],'-----',i['King'])

cls = db.class0
# for i in cls.find({'age':{"$lt":20}}):
#     print(i['name'],':',i['age'])

#通过cursor可以使用find后内容的修饰函数
print(cursor.count())

# for i in cursor.skip(2).limit(3):
#     print(i)
#cursor 为迭代的,取值后就不能sort了
# for i in cursor.sort([('name',1)]):
#     print(i)

# print(cursor.next())
#先写出字典比表示query然后传入
# dic = {'$or':[{'name':'宝强'},{'age':{'$gt':18}}]}
# for i in cls.find(dic):
#     print(i)


# data = cls.find_one(dic)
# cls.remove(data['_id'])

#修改

# my_set.update({'name':'张国立'},{'$set':{'name':'陈道明'}})
# my_set.update({'name':'郑少秋'},{'$set':{'King':'乾隆'}},upsert=True)#upsert可不写
# my_set.update({'King':'康熙'},{'$set':{'King_name':'玄烨'}},False,multi=True)#multi必须写

# my_set.update_many({'King':'雍正'},{'$set':{'King_name':'玄训'}})

print(my_set.find_one_and_delete({'name':'张铁林'}))

conn.close()#关闭数据库连接
View Code

    聚合
        1、aggregate()
            1、功能:实现MongoDB的聚合操作
            2、参数:与mongoshell中的聚合函数参数一样,在使用聚合操作符时用引号变为字符串即可
            3、返回值:迭代对象,同find的返回类型

from pymongo import MongoClient,IndexModel

conn = MongoClient('localhost',27017)
db = conn.stu
my_set = db.class3
cls = db.class0

#索引操作
# index = my_set.ensure_index('name')
# print(index)
#创建符合索引,1表示升序,-1表示降序
# index = my_set.ensure_index([('name',1),("King",-1)])
# print(index)


#先生成索引对象
# index1 = IndexModel([('name',1),('King',-1)])
# index2 = IndexModel([('King_name',1)])
# #将索引对象使用create_indexes生成索引
# indexes = my_set.create_indexes([index1,index2])
# print(indexes)

#唯一索引
# index = cls.ensure_index('name',unique =True,sparse=True)
# print(index)

#查看指定集合中的索引
# for i in my_set.list_indexes():
#     print(i)
# #删除索引
# # my_set.drop_index('name_1')
# print('******************************')
# my_set.drop_indexes()
# for i in my_set.list_indexes():
#     print(i)

#聚合操作
l = [{'$group':{'_id':'$King','count':{"$sum":1}}}]

cursor = my_set.aggregate(l)
for i in cursor:
    print(i)
View Code

文件的存储:
    1、gridfs文件提取

#获取数据库中gridfs文件
from pymongo import MongoClient
import gridfs

conn = MongoClient('localhost',27017)

db = conn.grid

#获取gridfs对象
fs = gridfs.GridFS(db)

files = fs.find()
print(files)
print(files.count())
#files为可迭代对象,每个迭代的结果为一个存入文件的对象,通过属性可以获取文件信息
# for file in files:
#     print(file.filename)
    
for file in files:
    with open(file.filename,'wb') as f:
        while True:
            data = file.read(64)#file对象有read接口可以直接从数据库读取内容
            if not data:
                break
            f.write(data)
conn.close()
View Code

    2、普通文件以二进制方式存入数据库

from pymongo import MongoClient
import bson.binary

#连接数据库
conn = MongoClient('localhost',27017)
#创建数据库
db = conn.savefile
#创建一个集合
my_set = db.image

file = './image.jpg'

#存储
#打开一个文件
# f = open(file,'rb')
# #将读取的二进制字节流,变为bson格式的二进制字串
# dic = dict(content=bson.binary.Binary(f.read()),filename='img.jpg')

# my_set.save(dic)

#提取文件
#获取存储文件的文档字典
data = my_set.find_one({'filename':'img.jpg'})

with open('img.jpg','wb') as f:
    f.write(data['content'])
conn.close()
View Code       

Python操作MongoDB数据库

import pymongo
#链接mongoDB数据库
conn = pymongo.MongoClient('localhost',27017)
#创建数据库并得到数据库对象
db = conn.testpymongo
#创建集合并得到集合对象
myset = db.t1
#向集合中插入一个数据
myset.insert({"name":"Tom"})
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!