zoukankan      html  css  js  c++  java
  • MongDB数据库

    • MongoDB的介绍

      

      MongoDB——一种非关系型数据库,是一个基于分布式文件存储的开源数据库系统。Mongodb 是目前最流行的 NoSQL 数据库之一,使用的数据类型 BSON(类似 JSON)。

      MongoDB相比较MySQL,MongoDB数据库更适合那些读作业较重的任务模型。MongoDB能充分利用机器的内存资源。如果机器的内存资源丰富的话,MongoDB的查询效率会快很多。总结为三点:一,易扩展。二,大数据量高性能。三,灵活的数据模型。

    • MongoDB的安装
    1. 从官网下载安装包

       下载地址:http://www.mongodb.org/downloads(注意有32位和64位之分)

        2.安装

    除了第二步勾选‘i accept。。。’外,一直点Next就行了。

    安装完成后查看bin文件夹,会看到些文件:

        3.启动MongoDB数据库

      安装完成后,在命令窗口输入mongo可以查看版本。

    启动方式1: 启动: sudo service mongod start

         停止: sudo service mongod stop

         重启: sudo service mongod restart

         配置文件的位置:/etc/mongod.conf

         日志的位置:/var/log/mongodb/mongod.log

         默认端⼝:27017

    启动方式2:

    启动: sudo mongod [--dbpath=dbpath --logpath=logpath --append -fork] [–f logfile ] 。只以 sudo mongod 命令启动时,默认将数据存放在了 /data/db 目录下,需要手动创建

    --dbpath: 指定数据库的存放路径

    --logpath: 指定日志的存放路径

    --logappend: 设置日志的写入形式为追加模式

    -fork: 开启新的进程运行mongodb服务

    f: 配置文件(可以将上述配置信息写入文件然后通过本参数进行加载启动) 

    客户端mongo启动:

    启动本地客户端:mongo

    查看帮助:mongo –help

    退出:exit或者ctrl+c

    远程连接   命令: mongo xxx.xxx.xxx.xxx:27017/admin -uusername -p 输入password即可

    • MongoDB的权限管理

    1.   为什么要进行权限管理的设置?

        刚安装完毕的mongodb默认不使用权限认证方式启动,与MySQL不同,mongodb在安装的时候并没有设置权限,然而公网运行系统需要设置权限以保证数据安全,所以我们要学习mongodb的权限管理。

    2.    MongoDB的权限管理方案

      MongoDB是没有默认管理员账号,所以要先添加管理员账号,并且mongodb服务器需要在运行的时候开启验证模式 用户只能在用户所在数据库登录(创建用户的数据库),包括管理员账号。 管理员可以管理所有数据库,但是不能直接管理其他数据库,要先认证后才可以。

    3.  MongoDB超级管理员账号的创建

      (3.1) 以权限认证的方式启动mongodb数据库

          sudo mongod -auth

          启动之后在启动信息中会有如下信息,说明mongodb以权限认证的方式启动成功

          [initandlisten] options: { security: { authorization: "enabled" } }

      (3.2)创建超级用户 使用admin数据库(超级管理员账号必须创建在该数据库上)

          use admin 创建超级用户

          db.createUser({"user":"python","pwd":"python","roles":["root"]})

          创建成功会显示如下信息:

          Successfully added user: { "user" : "python", "roles" : [ "root" ] }

      (3.3)退出客户端再次登录验证 此时再使用数据库各命令的时候会报权限错误,需要认证才能执行相应操作

          use admin

          db.auth('python','python')

          1

          python用户是创建在admin数据库上的所以必须来到admin数据库上进行认证,认证成功会返回1,失败返回0

    • MongoDB的基本操作

      1. mongodb数据库的命令

        查看当前的数据库:db(没有切换数据库的情况下默认使用test数据库)

        查看所有的数据库:show dbs /show databases

        切换数据库:use db_name

        删除当前的数据库:db.dropDatabase()

      2. mongodb集合的命令

        不手动创建集合: 向不存在的集合中第⼀次加⼊数据时, 集合会被创建出来

        手动创建结合: db.createCollection(name,options)

               db.createCollection("stu")

               db.createCollection("sub", { capped : true, size : 10,max:10 } )

               参数capped: 默认值为false表示不设置上限,值为true表示设置上限

               参数size: 当capped值为true时, 需要指定此参数, 表示上限⼤⼩,当⽂档达到上限时, 会将之前的数据覆盖, 单位为1KB=1024B

               max:条数

               查看集合:show collections

               删除集合:db.集合名称.drop()

               检查集合是否有上限: db.集合名.isCapped()

      3. mongodb中常见的数据类型

        Object ID: ⽂档ID

        String: 字符串, 最常⽤, 必须是有效的UTF-8

        Boolean: 存储⼀个布尔值, true或false

        Integer: 整数可以是32位或64位, 这取决于服务器

        Double: 存储浮点值

        Arrays: 数组或列表, 多个值存储到⼀个键

        Object: ⽤于嵌⼊式的⽂档, 即⼀个值为⼀个⽂档

        null: 存储null值

        Timestamp: 时间戳, 表示从1970-1-1到现在的总秒数123123123123

        Date: 存储当前⽇期或时间的UNIX时间格式

        >Date() :当前时间

        >ISODate("2016-01-24T12:52:33.341Z").valueOf() :时间戳(毫秒)

        注意点:

          每个⽂档都有⼀个属性, 为_id, 保证每个⽂档的唯⼀性,mongodb默认使用_id作为主键

           可以⾃⼰去设置_id插⼊⽂档,如果没有提供, 那么MongoDB为每个⽂档提供了⼀个独特的_id, 类型为objectID

          objectID是⼀个12字节的⼗六进制数,每个字节两位,一共是24 位的字符串: 前4个字节为当前时间戳 接下来3个字节的机器ID 接下来的2个字节中MongoDB的服务进程id 最后3个字节是简单的增量值。

    • MongoDB的增删改查
    1.           db.collection_name.insert({"_id":"111"})
          _id如果已经存在,insert方法会报错,不存在的时候,会插入新数据
     
    1.   db.collection_name.save({"_id":"111","name":"bob","age":"18"})
          _id如果存在,会更ddvd cx x新其他键对应的值(name,age),不存在的时候,会新插入数据
    1.    db.collection_name.remove({条件},{justOne:true})
          默认情况下,会删除全部满足条件的内容,justOne:true时值删一条
     
    1.    db.collections_name.drop()
          删除整个集合(collections_name)
     
      1.   db.collections_name.update({name:"bon"},{name:"fan"})
          更新 将名字为”bon”改为”fan” 弊端:会将collections_name内容代替  如:  db.text01.find() 
          { "_id" : "3", "name" : "fan", "age" : "16" } 
          db.text01.update({name:"fan"},{name:"xlnx"}) 
          { "_id" : "3", "name" : "xlnx" } 
     
      2.   db.collections_name.update({nmae:"bob"},{$set:{name:"fan"}})
          只能修改一条数据,并不会代替,将bob修改为fan
     
      3.   db.collection_name.update({条件},{$set:{name:jack}},{multi:true})
          在原有数据下,如果存在指定想修改的那个个条件,那就修改,如果不存在,就增加这一条数据。如果为False,就不执行
          默认情况下会修改一条,multi:true时可以修改满足条件的全部数据
     
          注意:multi update only works with $ operatorsmulti:true 只能跟$set连用

      1.⽅法  find(): 查询

        db.集合名称.find({条件⽂档})

      2. ⽅法  findOne():查询,只返回第⼀个

        db.集合名称.findOne({条件⽂档})

       3.⽅法  pretty(): 将结果格式化

        db.集合名称.find({条件⽂档}).pretty()

        db.collection_name.find({"age":16})       查询年龄为16
        db.collections_name.findOne()       查询只返回第一个
        db.collections_name.find().pretty()    将查询结果格式化
     
     
    • 比较运算符
        等于 默认就是等于判断,没有运算符
        大于 $gt        db.collection_name.find({age:{$gt:18}}) 查询年龄大于18
        大于等于$gte    db.collection_name.find({age:{$gte:18}})
        小于 $lt         db.collections_name.find({age:{$lt:18}})查询年龄小于18
        小于等于$lte    db.collection_name.find({age:{$lte:18}})
        不等于 $ne      db.collection_name.find({age:{$ne:18}})
     
        db.student.find({'price':{$lte:6000,$gt:500},'color':'bule'})  小于等于6000大于500并且颜色为蓝色
     
    • 逻辑运算符
        and 
        在JSON中写多个条件即可:查询年龄大于或等于18, 并且性别为true的学生
        db.collections_name.find({age:{$gte:18}},gender:"true"})
        or $or 
        使用$or 值为数组,数组中每个元素为json:查询年龄大于18, 或性别为false的学生
        db.collection_name.find({$or:[{age:{$gte:18}},{gender:true}]})
        形式 db.collection_name.find({$or:[{条件1},{条件2},{条件3}.....]})
    • 范围运算符
        ”in","in","nin” 判断是否在某个范围内
            查询年龄为18、 28
            db.collection_name.find({age:{$in:[18,28]}})
        $nin     不在范围内
            db.collections_name.find({age:{$gt:{$in:[25,16]}}})
     
    • 支持正则表达式(两种方式)
        使用 /xxx/ 
            db.collection_name.find({sku:/^a/}) 查找sku字段中以a开头的
            db.collections_name.find({sku:/9$/})查找sku字段中以9结尾的
        $regex     编写正则 值必须时字符串 
            db.collection_name.find({sku:{$regex:"^a"}})查找sku字段中以a开头的
            db.collections_name.find({sku:{$regex:"9$""}})查找sku字段中以9结尾的
     
    • limt        skip
       方法  limit()用于读取指定数量的文档
        db.集合名称.find().limit(NUMBER) 
        db.collection_name.find().limit(2)取两条
       方法  skip()用于跳过指定数量的文档
        db.集合名称.find().skip(NUMBER) 
        db.collection_name.find().skip(2)跳过两条
      连用 
        db.collection_name.find().limit(2).skip(2)先取两页再跳过2条
        db.collections_name.find().skip(2).limi(2)先跳两页,再取2条 —–比较高效常用
     
    • sort排序
        db.collections_name.find({}).sort({name:1,gender:-1})
          1为升序,-1为降序
    • 统计 count
        db.collections_name.find().count()
        db.collections_name.count({gender:true})  统计geder:true的个数
    • 去重distinct
        db.collections_name.distinct("去重字段",{条件})
        例:
        db.collections_name.distinct("hometown",{gneder:true,age:{$gt:18}}) 
        给hometown字段去重,并且gender为true ,age大于18的
        返回的是一个列表
     
    • MongDB的聚合操作

        聚合(aggregate):是基于数据处理的聚合管道,每个文档通过一个由多个阶段(stage)组成的管道,可以对每个阶段的管道进行分组、过滤等功能,然后经过一系列的处理,输出相应的结果。

           db.collections_name.aggregate(管道:{表达式})

    常用管道命令
     
          $group        将文档分组,可用于统计结果
          $match        过滤数据,输出符合条件的文档
          $project        修改输入文档的结构,如:重命名,增加,删除字段,创建统计结果(就是把计算完的结果输出)
          $sort             将文档排序后,输出
          $limt             限制聚合管道返回的档数,取几条
          $skip        跳过指定数量的文档, 并返回余下的文档
          $unwind        将数组类型的字段进行拆分
    表达式
    处理输出文档并输出
    语法:表达式:'$列名' {$..:{}}
     
    常用表达式:
          $sum:计算总和,sum:计算总和,sum:1 表示以1倍计数 表示把每一条数据当作1来计算
          $avg: 计算平均值
          $min: 获取最小值
          $max: 获取最大值
          $push: 在结果文档中插入值到一个数组中  插入的值必须是中括号
          $first: 根据资源文档的排序获取第1个文档数据
          $last: 根据资源wenwen档的排序获取最后1个文档数据
    动手
    将⽂档中的某⼀个数组类型字段拆分成多条, 每条包含数组中的⼀个值 
          语法:db.集合名称.aggregate({unwind:′unwind:′字段名称’})
    投影
    返回特定的字段
          db.collection_name.find({条件},{name:1,_id:0})
          _id 不需要显示的时候,值为0,其他字段不需要的时候,不写即可显示时值为1
          db.collections_name.find({条件},{name:1,_id:0}) 显示name 不显示其他字段,不需要id时就爱那个id设为0
    统计个数
          db.collection_name.find({条件}).count()
          db.collection_name.count({条件})
    去重
          db.stu.distinct(“hometown”,{gender:true,age:{$gt:18}})
          返回数组
     
    • 索引操作

    1.为什么mongdb需要创建索引?

       加快查询速度 进行数据的去重

    2.mongodb创建简单的索引方法 :

    注意:从 mongoDB 3.0 开始,ensureIndex 被废弃,今后都仅仅是 createIndex 的一个别名。

          db.p2p.opinion.createIndex({'author':1});    创建
          db.p2p.opinion.getIndexes();    查看
          db.p2p.opinion.dropIndex({'author':1});    删除
     
    创键索引 
          db.colllectons_name.ensureIndex({属性:1})
          语法:db.集合.ensureIndex({属性:1})  1表示升序, -1表示降序具体操作:`db.t1.ensureIndex({name:1})
          db.collection_name.creatreIndex({属性:1}).explain('executionStats')explain(‘executionStats’)   查看查询的时间
    创建唯一索引 
          db.collections_name.createindex({name:1},{"unique":true})
          db.集合.creteindex({属性:1})       1表示升序,-1表示降序
    创建联合索引——去重一般用三个字段 
          db.collection_name.ensureindex({name:1,age:1})
    查看索引 
          db.collection_name.getindexes()
    删除索引 
          db.collection_name.dropindex()
    数据去重
    数据库建立索引,需要建立联合索引,通过数据库来实现数据的自动去重。
    根据url地址去重,把url地址存在redis的集合中,后续新来一个url地址,判断他是否存在redis中,不存在才抓取。 
    url对应的响应不会变化的时候,使用sha1加密数据(可以选择加密某些字段),把得到的结果存入redis的集合中,后续新抓到的数据同样的方式进行加密,判断得到的值在redis的集合中是否存在,存在就更新,不存在就插入。

    3. 创建索引前后查询速度对比

    测试:

    插入10万条数据到数据库中 插入数据:   for(i=0;i<100000;i++){db.t1.insert({name:'test'+i,age:i})}

    创建索引前:     db.t1.find({name:'test10000'}) db.t1.find({name:'test10000'}).explain('executionStats')

    创建索引后:     db.t255.ensureIndex({name:1}) db.t1.find({name:'test10000'}).explain('executionStats')

    前后速度对比:

    • 数据库的备份恢复与导出导入
     
    数据库的备份        mongodump -h hostname -d db -o path
    数据库的恢复        mongorestore -h hostname -d db -dri path
    导出         mongoexport -u -p --authorization
    导入         mongoimport -u -p --authorization
              -h: 服务器地址
              -d: 数据库名
               -c: 集合名
               -o: 导出文件名 
              --type: 文件类型,默认json格式,可选数据类型json,csv -f: 需要导出的字段,导出为json格式的数据时可以不指定导出哪些字段,默认全部,导出成csv文件是必须指定
     
    • mongo和python交互

    1. mongdb和python交互的模块

      pymongo 提供了mongdb和python交互的所有方法 安装方式: pip install pymongo

    from pymongo import MongoClient
    
    
    class MongoUtil(object):
    
        def __init__(self,host,port,db):
            self.conn = MongoClient(host=host,port=port)
            self.db = self.conn[db]
    
        def get_state(self):
            return True
    
        def auth(self,name,password,source):
            '''
            登录
            :param name:用户名
            :param password:密码
            :param source:授权数据库
            :return: true/false
            '''
            if self.get_state():
                try:
                    return self.db.authenticate(name=name,password=password,source=source)
                except:
                    return False
            else:
                return False
    
        def insert_one(self,collection,document):
            '''
            插入单条
            :param collection: 集合名
            :param document: 文档(单条),类型:dict
            :return: 插入的这条数据的ID
            '''
            if self.get_state():
                result = self.db[collection].insert_one(document=document)
                return result.inserted_id
            else:
                return ''
    
        def insert_many(self,collection,documents):
            '''
    
            :param collection: 集合名
            :param documents: 文档(多条),类型:list(dict)
            :return: 受影响的ID
            '''
            if self.get_state():
                result = self.db[collection].insert_many(documents=documents)
                return result.inserted_ids
            else:
                return ''
    
        def update_one(self,collection,filter,update,upsert=False):
            '''
    
            :param collection:
            :param filter:
            :param update:dict
            :param upsert:
            :return:修改后的结果
            '''
            if self.get_state():
                return self.db[collection].update_one(filter=filter,update=update,upsert=upsert)
            else:
                return None
    
        def update_many(self,collection,filter,update,upsert=False):
            '''
    
            :param collection:
            :param filter:
            :param update:list(dict)
            :param upsert:
            :return:修改后的结果
            '''
            if self.get_state():
                return  self.db[collection].update_many(filter=filter,update=update,upsert=upsert)
            else:
                return None
    
        def find(self,collection,filter=None,column=None):
            '''
    
            :param collection:集合名
            :param filter:过滤器
            :param column:投影
            :return:结果集
            '''
            if self.get_state():
                result = self.db[collection].find(filter,column)
                return result
            else:
                return None
    
        def  delete_one(self,collection,filter):
            '''
            :param collection:
            :param filter:
            :return:删除的条数
            '''
            if self.get_state():
                return self.db[collection].delete_one(filter=filter)
            else:
                return 0
    
        def  delete_many(self,collection,filter):
            '''
            :param collection:
            :param filter:
            :return:删除的条数
            '''
            if self.get_state():
                return self.db[collection].delete_many(filter=filter)
            else:
                return 0
    
        def aggregate(self,collection,pipline):
            '''
    
            :param collection:
            :param pipline: 管道(如果多个阶段,需要list,例如:[{'$group':...},{'$match':...}])
            :return:
            '''
            if self.get_state():
                result = self.db[collection].aggregate(pipeline=pipline)
                return result
            else:
                return None
    
        def close(self):
            self.conn.close()
    
    
    
    if __name__ == '__main__':
        # 链接mongo
        mongo = MongoUtil(host='192.168.1.29',port=27017,db='python')
        # 授权
        result = mongo.auth(name='liumingyi',password='123456',source='admin')
        if result:
            # 操作:单条插入
            insertID = mongo.insert_one(collection='car',document={'car':'奥拓','price':3000})
            #输出刚才插入的数据
            result = mongo.find(collection='car',filter={'_id':insertID})
            for i in result:
                print(i)
            # 更新
            # result = mongo.update_one(collection='car',filter={'name':'奥拓5'},update={'$set':{'price':5000}},upsert=True)
            # print(result)
            # result = mongo.update_many(collection='car', filter={'car': '奥拓'}, update={'$set': {'price': 5000}})
            # print(result)
    
            # 删除
            result = mongo.delete(xxx)
    
        else:
            print('授权失败')

    2 .使用pymongo如果理解麻烦的话,那再来个简化版的:

    from pymongo import MongoClient
    
    #1.连接mongo
    con = MongoClient(host='localhost',port=27017)
    #2.连接数据库
    db = con['python']
    #3.授权
    db.authenticate(name='wangrui',password='123456',source='admin')
    #4.连接集合
    coll = db['car']
    #5.查找操作
    result = coll.find({'carname':'宝马'},{'_id':0,'carname':1,'price':1})
    for i in result:
        print(i)
    
    #6.更新
    result = coll.update_one({'carname':'宝马'},{'$set':{'carname':'玛莎拉蒂'}})
    print(result)
    
    #7.增加
    result = coll.insert_one({'carname':'兰博基尼','price':40000})
    
    #8.删除
    result = coll.delete_one({'carname':'兰博基尼'})
    print(result)
    
    #9.聚合
    result = coll.aggregate([{'$group':{'_id':'$carname','count':{'$sum':1}}}])
    for i in result:
        print(i)

    好了,结束,祝大家天天愉快!^_^

  • 相关阅读:
    【Head First Servlets and JSP】笔记
    【Java Web】新手教程(转)
    【Java Web】入门资源整理
    【离散数学】网络资源整理
    【c++习题】【17/5/8】重载运算符
    【c++习题】【17/4/13】stack
    【笔记】css3实现网页平滑过渡效果...
    【Python】常用内建模块(卒)
    【Java】仿真qq尝试:用户注册(三)
    【Thinking in java, 4e】复用类
  • 原文地址:https://www.cnblogs.com/onerose/p/10241512.html
Copyright © 2011-2022 走看看