MongoDB

 

 

MongoDB 

    非关系型数据库
        nosql的介绍
            “NoSQL”一词最先于1998年被用于多个轻量级的关系数据库的名字
            随着web2.0的快速发展,NoSQL概念在2009年被提了出来
            NoSQL在2010年起,如今国内外众多应用网站, 如facebook、 google、 淘宝、 京东、 百度等
            都在使用nosql开发高性能的产品
            对于一名程序员来说,使用nosql已经成为一条必备技能
            NoSQL最经常使用的解释是"non-relational","Not Only SQL"也被不少人接受,指的是非关系型的数据库
        
        NOSQL和RDBMS的区别
            NOSQL:
                1)无需通过sql层的解析,读写性能很高
                2)基于键值对,数据没有耦合性,容易扩展
                3)存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,
                    而关系型数据库则只支持基础类型
                
            RDBMS:
                1)容易理解:二维表结构是很是贴近逻辑世界一个概念,关系模型相对网状、层次等
                    其余模型来讲更容易理解
                2)使用方便:通用的SQL语言使得操做关系型数据库很是方便
                3)易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了
                    数据冗余和数据不一致的几率
                4)支持SQL,可用于复杂的查询
                
        MongoDB的优点:
            1)更高的写负载能力
                默认状况下,对比事务安全,MongoDB更关注高的插入速度,若是你须要加载大量低价值的
                业务数据,好比日志收集,那么MongoDB将很适合你的用例,可是必须避免在要求高事务安全
                的情景下使用MongoDB,好比金钱交易
            2)处理很大的规模的单表
                数据库扩展是很是有挑战性的,当单表格大小达到5-10GB时,MySQL表格性能会毫无疑问的下降。
                若是你须要分片而且分割你的数据库,MongoDB将很容易实现这一点
            3)不可靠环境保证高可用性
                设置副本集(主-从服务器设置)不只方便并且很快,此外,使用MongoDB还能够快速、
                安全及自动化的实现节点(或数据中心)故障转移
            4)使用基于位置的数据查询,查的更快
                MongoDB支持二维空间索引,好比管道,所以能够快速及精确的从指定位置获取数据,
                MongoDB在启动后会将数据库中的数据以文件映射的方式加载到内存中,若是内存资源至关丰富的话,
                这将极大地提升数据库的查询速度,由于内存的I/O效率比磁盘高多了
            5)非结构化数据的爆发增加
                增长列在有些状况下可能锁定整个数据库,或者增长负载从而致使性能降低,这个问题一般发生
                在表格大于1GB的状况下,鉴于MongoDB的弱数据结构模式,添加1个新字段不会对旧表格有任何影响,
                整个过程会很是快速;所以,在应用程序发生改变时,你不须要一个专门的DBA去修改数据库模式
            6)缺乏专业的数据库管理员
                若是你没有专业的DBA,同时你也不须要结构化你的数据及作join查询,MongoDB将会是你的首选,
                MongoDB很是适合类的持久化,类能够被序列化成JSON并储存在MongoDB;须要注意的是,
                若是指望得到一个更大的规模,你必需要了解一些最佳实践来避免走入误区
            
    常见类型数据类型:
        1)null。{"x":null}
        2)Boolean。{"x":true} 、{"x":false}
        3)数据类型
            在Mongodb     Shell中默认使用64位浮点型数据,如{"x":2.32}、{"x":2},若是要使用整数类型则用
            {"x":NumberInt(2)}、{"x":NumberLong(2)}
        4)字符串。Mongodb中字符串采用UTF-8编码方式,{"x":"hello world"}
        5)日期类型。{"x":new Date()}
        6)正则表达式。 Mongodb中可以使用和javascript相同的正则表达式 {"x":/itbilu/i}
        7)数据。Mongodb中数组的使用和javascript相同{"x":["hello","world"]}
        8)内嵌文档。{"x":{"y":"Hello"}}
        9)Id和ObjectId(),Mongodb每一个文档都会生成一个_id,若是你不指定时Mongodb会自动生成一个ObjectId对象,
        10)代码。{"x":function aa(){}}
        11)二进制
        
    MongoDB的操做
        默认端口号:27017
        进入数据库
            mongo
            
        查看当前所在的数据库
            db 
            
        查看全部的数据库(2)    
            show dbs/show databases
            
        使用数据库
            use texts
            
        删除数据库
            db.dropDatabase()

        集合(至关于关系型中的数据表)
            查看全部集合
                show collections
            
            建立集合
                格式:
                    db.create.Collection(name,options)
                建立一个名为test的集合    
                    db.create.Collection(test)
                
            删除集合
                db.text.drop()
                
            增长(插入)数据
                会自动生成一个"_id"字段
                db.test.insert({address:"陕西省西安市"})
                db.test.insert({address:"陕西省西安市草滩六路",tel:"13141939210",gender:"man"})
                
                保存数据
                    # 若是ID重复,自动转为更新
                    db.test.save({}) 
                
                查看全部数据
                    db.test.find()
                    
            修改(更新数据)
                # 先插入小明的数据 * 3
                    db.test.insert({name:"小明"})
                # 会把知足条件的第一条更新为{age:26}
                    db.test.update({name:"小明"},{age:"26"})
                # 只更新一条
                    db.test.update({name:"小明"},{$set:{age:"100"}})
                # 所有更新
                    db.test.update({name:"小明"},{$set:{age:"88"}},{multi:true})
            
            删除数据
                第一个参数为条件
                    # 所有删除
                        db.test.remove({name:"小明"},{justOne:"false"})
                    # 删除一条
                        db.test.remove({name:"小明"},{justOne:"true"})
                    
            查询数据
                普通查询
                    查看全部数据
                        db.test.find()
                    查看第一条数据
                        db.test.findOne()
                    pretty用来美化样式
                        db.test.find().pretty()
                
                # 构造查询数据
                db.test.insert([
                    {"name" : "郭靖", "hometown" : "蒙古", "age" : 20, "gender" : true },
                    {"name" : "黄蓉", "hometown" : "桃花岛", "age" : 18, "gender" : false },
                    {"name" : "华筝", "hometown" : "蒙古", "age" : 18, "gender" : false },
                    {"name" : "黄药师", "hometown" : "桃花岛", "age" : 40, "gender" : true },
                    {"name" : "段誉", "hometown" : "大理", "age" : 16, "gender" : true },
                    {"name" : "段王爷", "hometown" : "大理", "age" : 45, "gender" : true },
                    {"name" : "洪七公", "hometown" : "终南山", "age" : 18, "gender" : true }
                    ])
                    # true表明男  false表明女            
                        
                # 查询年龄等于18岁的
                    db.test.find({age:18}).pretty()
                # 查询年龄大于18岁的
                    db.test.find({age:{$gt:18}}).pretty()
                # 查询年龄大于等于18岁的
                    db.test.find({age:{$gte:18}}).pretty()
                # 查询年龄小于等于18岁的
                    db.test.find({age:{$lte:18}}).pretty()
                # 查询年龄不等于18岁的
                    db.test.find({age:{$ne:18}}).pretty()
                # 查询年龄大于18岁而且是男性的
                    db.test.find({$and:[{age:{$gt:18},gender:true}]}).pretty() 
                    db.test.find({age:{$gt:18},gender:true}).pretty()
                # 查询年龄小于等于18岁而且是男性的
                    db.test.find({age:{$lte:18},gender:true}).pretty()    
                # 查询年龄小于等于18岁而且是女性的
                    db.test.find({age:{$lte:18},gender:false}).pretty()
                # 查询年龄小于等于18岁或者是女性的
                    db.test.find({$or:[{age:{$lte:18}},{gender:false}]}).pretty()
                # 查询年龄大于18岁或者hometown是大理
                    db.test.find({$or:[{age:{$gt:18}},{hometown:"大理"}]}).pretty()
                # 查询年龄大于18岁的而且姓名是郭靖的,或者hometown是大理
                    # 先查找年龄大于18且姓名是郭靖的
                    db.test.find({age:{$gt:18},name:"郭靖"}).pretty()
                    # 再将hometown是大理的拼接进去
                    db.test.find({$or:[{age:{$gt:18},name:"郭靖"},{hometown:"大理"}]}).pretty()
                # 查询年龄是18,20,45的
                    db.test.find({age:{$in:[18,20,45]}}).pretty()
                    
                skip和limit使用
                    注意:
                        先使用skip在使用limit的效率要高于前者
                    skip:
                        跳过指定的文档
                    limit:
                        读取指定的文档
                    
                    # 获取test集合的前三条
                        db.test.find().limit(3).pretty()
                    # 跳过test集合的前三条,从后面取两条    
                        db.test.find().skip(3).limit(2).pretty()
                    
                还支持正则表达式
                    db.products.insert([    
                        { "_id" : 100, "sku" : "abc123", "description" : "Single line description." },
                        { "_id" : 101, "sku" : "abc789", "description" : "First line\nSecond line" },
                        { "_id" : 102, "sku" : "xyz456", "description" : "Many spaces before line" },
                        { "_id" : 103, "sku" : "xyz789", "description" : "Multiple\nline description" }    
                    ])

                    # 查询以xyz开头的sku
                        第一种方法:
                            db.products.find({"sku":/^xyz/}).pretty()
                        第二种方法:
                            db.products.find({sku:{$regex:"^xyz"}}).pretty()
                    
                
                
                自定义查询方法
                    有点像js代码
                        # 年龄大于30的英雄
                        db.test.find({
                             $where:function() {
                             return this.age>30;}
                     }).pretty()

                投影
                    注意:
                        第一个参数{}必传
                        在查询到的返回结果中,只选择必要的字段
                        命令:db.集合名称.find({},{字段名称:1,...})
                            参数为字段与值,值为1表示显示,值为0不显特别注意:对于_id列默认是显示 
                            若是不显示须要明确设置为0
                        
                        # 只显示name和age字段,其他字段不显示
                        db.test.find({},{"_id":0,name:1,age:1}).pretty()
                排序
                    命令:db.集合名称.find().sort({字段:1,...})
                        参数1为升序排列 参数-1为降序排列
                        
                        # 根据_id降序,年龄增序
                        # 先根据_id降序
                        db.test.find().sort({"_id":-1}).pretty()
                        db.test.find().sort({"_id":-1,age:1}).pretty()
                
                 统计个数
                    命令:db.集合名称.find({条件}).count() 命令:db.集合名称.count({条件})
                    # 统计性别为ture的个数
                    db.test.find({gender:true}).count()
                    # 统计hometown为大理的个数
                    db.test.find({hometown:"大理"}).count()
                    
                消除重复
                    注意:
                        返回的是一个列表
                    命令:db.集合名称.distinct('需去重字段',{条件})
                        # 根据hometown去重,age是大于18的
                        db.test.distinct("hometown",{age:{$gt:18}})
                        # 根据gender去重,age是大于等于18的
                        db.test.distinct("gender",{age:{$gte:18}})
                    
                mongodb的聚合    
                    聚合(aggregate)是基于数据处理的聚合管道,每一个文档经过一个由多个阶段(stage)
                    组成的管道,能够对每一个阶段的管道进行分组、过滤等功能,而后通过一系列的处理,
                    输出相应的结果

                    语法:db.集合名称.aggregate({管道:{表达式}})
                    
               mongodb的经常使用管道和表达式
                    经常使用的管道以下
                        $group: 将集合中的文档分组,可便于统计结果
                        $match: 过滤数据,只输出符合条件的文档
                        $project: 修改文档的输入输出结构,如重命名,增长,删除字段,建立计算结果
                        $sort: 将输入的文档排序后输出
                        $limit: 限制聚合管道返回的文档数
                        $skip: 跳过指定数量的文档,并返回余下的文档    
                    
                    经常使用表达式
                        表达式: 处理输入文档并输出 
                        语法: 表达式:'$列名' 经常使用表达式
                            $sum: 计算总和, $sum:1 表示以一倍计数
                            $avg: 计算平均值
                            $min: 获取最小值
                            $max: 获取最大值
                            $push: 在结果文档中插入值到整个数组中
                            
                    
                    管道命令之$group
                        # 先对gender过滤,再对hometown进行分组,并计算年龄和
                    
                        db.test.aggregate([
                                {$match:{gender:true}},
                                {$group:{_id:"$hometown",calc_age:{$sum:"$age"}}}
                            ])
                                    
                    group by null
                        当咱们须要统计整个文档的时候,$group 的另外一种用途就是把整个文档分为一组进行统计
                        使用实例以下:
                            db.test.aggregate(
                                    {$group:
                                        {
                                            _id:null,
                                            counter:{$sum:1}
                                        }
                                    }
                                )
                        其中注意点
                            _id:null 
                            表示不指定分组的字段,即统计整个文档,此时获取的counter表示整个文档的个数    
                        
                                    
                    数据透视
                        正常状况在统计的不一样性别的数据的时候,须要知道全部的name,须要逐条观察,
                        若是经过某种方式把全部的name放到一块儿,那么此时就能够理解为数据透视
                        
                        统计不一样的学生
                            注意:
                                查询出name:后面是一个列表
                            1)db.test.aggregate(
                                 {$group:
                                     {
                                         _id:null,
                                         name:{$push:"$name"}
                                     }
                                 }
                            )

                            使用$$ROOT能够将整个文档放入数组中
                            2)db.test.aggregate(
                                 {$group:
                                     {
                                         _id:null,
                                         name:{$push:"$$ROOT"}
                                     }
                                 }
                            )    
                练习:
                    db.example.insert([
                        { "country" : "china", "province" : "sh", "userid" : "a" },  
                        {  "country" : "china", "province" : "sh", "userid" : "b" }, 
                        {  "country" : "china", "province" : "sh", "userid" : "a" },  
                        {  "country" : "china", "province" : "sh", "userid" : "c" },  
                        {  "country" : "china", "province" : "bj", "userid" : "da" },  
                        {  "country" : "china", "province" : "bj", "userid" : "fa" }
                    
                    ])
                        
                # 须要统计出每一个country/province下的userid的数量(同一个userid只统计一次)

                db.example.aggregate(
                {$group:{"_id":{"country":"$country","province":"$province","userid":"$userid"}}},
                {$group:{"_id":{"country":"$_id.country","province":"$_id.province"},count:{$sum:1}}},
                {$project:{"_id":0,"country":"$_id.country","province":"$_id.province","count":"$count"}}
            
                )
                    
                    管道命令之$match
                        # 查询年龄大于20的学生
                             db.test.aggregate(
                                 {$match:{age:{$gt:20}}
                                 )
                        # 查询年龄大于20的男女学生的人数
                             db.test.aggregate(
                                 {$match:{age:{$gt:20}}
                                 {$group:{_id:"$gender",counter:{$sum:1}}}
                                 )
                                 
                    管道命令之$project
                        # 查询学生的年龄、姓名,仅输出年龄姓名
                             db.test.aggregate(
                                 {$project:{_id:0,name:1,age:1}}
                                 )
                        # 查询男女生人生,输出人数
                             db.test.aggregate(
                                 {$group:{_id:"$gender",counter:{$sum:1}}}
                                 {$project:{_id:0,counter:1}}
                                 )
                        
                    管道命令之$sort
                        # 查询学生信息,按照年龄升序
                            db.test.aggregate({$sort:{age:1}})
                        # 查询男女人数,按照人数降序
                            db.test.aggregate(
                                    {$group:{_id:"$gender",counts:{$sum:1}}},
                                    {$sort:{counts:-1}}
                                )
                    管道命令之$skip和$limit
                        # 查询2条学生信息
                            db.test.aggregate(
                                {$limit:2}
                            )
                            
                        # 查询从第三条开始的学生信息    
                            db.test.aggregate(
                                {$skip:3}
                            )
                        # 统计男女生人数,按照人数升序,返回第二条数据    
                            db.test.aggregate(
                                {$group:{_id:"$gender",counts:{$sum:1}}},
                                {$sort:{counts:1}},
                                {$skip:1},
                                {$limit:1}    
                            )
                    
                    
        索引
            普通索引
                mongodb建立简单的索引方法
                    db.test01.ensureIndex({属性:1}),1表示升序, -1表示降序
                    db.test01.createIndex({属性:1})
                    
                    # 插入10万条测试数据
                        for(i=0;i<100000;i++){
                                
                                db.test01.insert({name:'test'+i,age:i})
                            }
                        
                    建立索引前:
                        db.test01.find({name:'test10000'})
                        db.test01.find({name:'test10000'}).explain('executionStats')
                        在executionStats中查找
                            executionTimeMillis : xx
                    建立索引后:
                        db.test01.ensureIndex({name:1})
                        db.test01.createIndex({name:1})
                        db.test01.find({name:'test10000'}).explain('executionStats')
                        在executionStats中查找
                            executionTimeMillis : xx
                            
                
                查看索引
                    默认状况下_id是集合的索引
                    查看当前集合中全部的索引
                        db.test01.getIndexes()
                        
            惟一索引
                db.test01.ensureIndex({"age":1},{"unique":true})
            
            删除索引
                db.test01.dropIndex({'name':1})
                db.test01.dropIndex({'age':1})
                
            创建复合索引
                创建复合索引的语法
                    db.test01.ensureIndex({name:1,age:1})
            
            建立索引的注意点
                索引不是越多越好
                根据须要选择是否须要创建惟一索引
                索引字段是升序仍是降序在单个索引的状况下不影响查询效率,可是带复合索引的条件下会有影响

                例如:在进行查询的时候若是字段1须要升序的方式排序输出,字段2须要降序的方式排序输出,
                    那么此时复合索引的创建须要把字段1设置为1,字段2设置为-1
            
        mongodb的备份和恢复
            备份
                -h: 服务器地址, 也能够指定端⼝号
                -d: 须要备份的数据库名称
                -o: 备份的数据存放位置, 此目录中存放着备份出来的数据
                mongodump -h dbhost -d dbname -o dbdirectory
                mongodump -h localhost:27017 -d test -o ~/Desktop/test12
                
            恢复
                -h:     服务器地址
                -d:     须要恢复的数据库实例
                --dir:  备份数据所在位置
                mongorestore -h loacalhost:27017 -d test --dir ~/Desktop/test11
                
                
        mongdb和python交互
            pip install pymongo
            from pymongo import MongoClient
            
            client = MongoClient(127.0.0.1,27017)
            collection = client[db名][集合名]
            
            # 添加一条数据
                ret = collection.insert_one({"name":"alex10010","age":33})
                print(ret)
                
            # 添加多条数据    
                item_list = [{"name":"alex1000{}".format(i)} for i in range(10)]
                
                #insert_many接收一个列表,列表中为全部须要插入的字典
                t = collection.insert_many(item_list)
                
            # 查找一条数据
                #find_one查找而且返回一个结果,接收一个字典形式的条件
                t = collection.find_one({"name":"alex10005"})
                print(t)
                
            查找所有数据
                结果是一个Cursor游标对象,是一个可迭代对象,能够相似读文件的指针,可是只可以进行一次读取
                #find返回全部知足条件的结果,若是条件为空,则返回数据库的全部
                t = collection.find({"name":"alex10005"})
                    #结果是一个Cursor游标对象,是一个可迭代对象,能够相似读文件的指针
                for i in t:
                    print(i)
                for i in t: 
                #此时t中没有内容
                     print(i)    
            
            # 更新一条数据 注意使用$set命令
                #update_one更新一条数据
                collection.update_one({"name":"alex10005"},{"$set":{"name":"new_alex10005"}})
                
            # 更行所有数据
                 # update_one更新所有数据
                 collection.update_many({"name":"alex10005"},{"$set":{"name":"new_alex10005"}})    
        
            # 删除一条数据
                 #delete_one删除一条数据
                 collection.delete_one({"name":"alex10010"})
        
            # 删除所有数据
                 #delete_may删除全部知足条件的数据
                 collection.delete_many({"name":"alex10010"})
                 
                 
        
        
        
    
    
相关文章
相关标签/搜索