zoukankan      html  css  js  c++  java
  • Python全栈 MongoDB 数据库(聚合、二进制、GridFS、pymongo模块)

    断网了2天  今天补上
     
     
    聚合操作:
    对文档的信息进行整理统计的操作
    返回:统计后的文档集合
    db.collection.aggregate()
    功能:聚合函数,完成聚合操作
    参数:聚合条件,配合聚合操作符使用
    返回:聚合后的结果
     
    常用聚合操作符:
    1.$group  分组聚合   要配合具体的统计操作符获取结果
     
    $sum  求和
    db.class1.aggregate({$group:{_id:'$gender',num:{$sum:1}}})
         分组   按照gender值统计 统计结果,求和每有一个加1
    统计所有男生和女生的年龄之和
    db.class1.aggregate({$group:{_id:'$gender',num:{$sum:'$age'}}})
     
    $avg  平均值
    求男生 女生年龄的平均数
     db.class1.aggregate({$group:{_id:'$gender',num:{$avg:'$age'}}})
     
    $max 求最大值
    求男生女生的年龄最大值
    db.class1.aggregate({$group:{_id:'$gender',num:{$max:'$age'}}})
     
    $min  求最小值
    求男生女生的年龄最小值
    db.class1.aggregate({$group:{_id:'$gender',num:{$min:'$age'}}})
     
    2.$project
    用于修改文档的显示效果
     
    $project值的用法同find()的field参数相同
    db.class1.aggregate({$project:{_id:0,name:1,age:1}})
     
    自定义显示的域名
    db.class1.aggregate({$project:{_id:0,Name:'$name',Age:'$age'}})
     
     
    3.$match
    过滤想要的数据
     
    过滤年龄大于30的数据,$match值的写法同query
     db.class1.aggregate({$match:{age:{$gt:30}}})
     
    4.$limit
    显示前几个文档
    db.class1.aggregate({$limit:3})
     
    5.$skip
    跳过前几个文档显示
     db.class1.aggregate({$skip:2})
     
    6.$sort   排序
     
    按照年龄排序
    db.class1.aggregate({$sort:{age:1}})
     
    聚合管道
    将前一个聚合操作产生的结果,交给后一个聚合操作继续使用
    db.collection.aggregate([{聚合1},{聚合2},{}...])
     
    $match --> $sort -->$project
     db.class1.aggregate([{$match:{gender:'m'}},{$sort:{age:1}},{$project:{_id:0}}])
     
    聚合示例
    使用grade数据库
    给更多同学添加 域score
    score:{english:87,chinese:76,math:91}
     
    1. 按照性别统计每组人数
    aggregate({$group:{_id:'$sex',num:{$sum:1}}})
     
    2. 统计该班中有哪个同学姓名为重名同学
    aggregate([{$group:{_id:'$name',num:{$sum:1}}},{$match:{num:{$gt:1}}}])
     
    3. 统计所有男生的语文成绩,只打印姓名,性别,语文成绩即可
    aggregate([{$match:{sex:'m'}},{$project:{_id:0,name:1,sex:1,'score.chinese':1}}])
     
    4. 将所有女生按照英语成绩降序排序
    aggregate([{$match:{sex:'w'}},{$sort:{'score.english':-1}}])
     
    文件存储:
     
    1.存储路径
    将文件放在本地路径(网络路径)下,然后数据库中存储该文件的查找路径
      
    优点 : 节省数据库空间
    缺点 : 当数据或者文件位置发生变化时文件即丢失
     
    2. 将文件转换为二进制,存储文件本身
     
    数据库支持二进制数据格式
    将文件转换为二进制格式,然后存入数据库中
     
    优点 : 数据库和文件绑定,数据库在文件即在
    缺点 : 占用数据库空间大,存取效率低
     
    mongodb存储文件本身
    * 如果是小文件建议转换二进制直接插入
    * 如果是大文件建议使用GridFS方案存储(大于16M)
     
    GridFS方案解释
     
    1. 在mongodb一个数据库中使用两个集合配合存储文件
    2. fs.files 用来存储文件的相关信息,为每一个文件创建一个文档,
       存储文件名,文件大小,存入时间。。。
    3. fs.chunks 用来分块存储文件的实际内容(Binary data 类型数据)
     
    存储方法:
    mongofiles  -d dbname(数据库)   put  file(要存储的文件)
                                             
     
    * 数据库不存在会自动创建数据库
      数据库中会自动创建fs.files  fs.chunks两个集合
     
    fs.files文档结构:
    {
    "_id" : ObjectId("5b7cdcd769d72e12b4f166d0"),
    "chunkSize" : 261120,
    "uploadDate" : ISODate("2018-08-22T03:47:35.381Z"),
    "length" : 305033,
    "md5" : "3698b5e762b5b396766aaf9feef7e10d", 
    "filename" : "file.jpg"
    }
     
    fs.chunks文档结构
    {
    "_id" : ObjectId("5b7cdcd769d72e12b4f166d2"),
    "files_id" : ObjectId("5b7cdcd769d72e12b4f166d0"), 
    "n" : 1, 
    "data" : BinData(0,"tQWR0AR......AG") 
    }
     
    * 同一个文件fs.files中的_id值等于fs.chunks中的    files_id域的值
     
    提取方法:
     
    mongofiles  -d  dbname   get  file
     
    GridFS方案:
    优点 : 存储方便,提供较好的命令支持和编程接口
    缺点 :  存取效率低下 还没有复制的快
     
    mongo shell中获取游标:
    * mongo shell下支持JS代码,可以通过JS获取游标,进而获取数据操作结果。
     
    var cursor = db.class1.find()
    cursor.next()   获取下一条结果
    cursor.hasNext()  查看是否有下一个对象
     
     
    通过python操作 MongoDB:
    pymongo 模块   第三方模块
    安装:
    sudo  pip3 install  pymongo
     
    操作步骤:
     
        1. 连接数据库,生成数据库连接对象
            conn = pymongo.MongoClient('localhost',27017)
     
        2. 选择要操作的数据库,生成数据库对象 (__setitem__)
            db = conn.stu
            db = conn['stu']
     
        3. 获取集合对象
            myset = db.class0
            myset = db['class0']
     
        4. 通过集合对象调用mongodb数据库操作函数
            增删改查,聚合,索引。。。。。
     
        5. 关闭数据库连接
               conn.close()
     
     
    插入文档:
     
    insert()    插入数据 功能同 mongoshell
    insert_many()   插入多条
    insert_one()  插入一条
    save()   插入数据,通过_id可以修改
     
     
    查找操作:
    find()
    功能 : 对数据库进行查找
    参数 : 同mongoshell  find()
    返回值 : 返回游标对象
                    cursor = myset.find({},{'_id':0})
    cursor的属性函数
    next()
    limit()
    skip()
    count()
    sort()
     
    Python中sort和MongoDB的区别
                    并且Python中的数据是字典和MongoDB的数据不同 
                    所以键和操作符号都必须要加引号
    pymongo  : sort([('age',-1),('name',1)])
    mongoshell : sort({age:-1,name:1})
     
    * 如果通过for或者next操作了游标对象,再调用limit,skip,sort会报错
     
    find_one()
    用法同mongoshell中 findOne()
    返回一个字典
     
     
    修改操作:
    update(query,update,upsert = False,multi = False)
    update_many()
    update_one()
     
    删除操作:
    remove(query,multi = True)
    功能: 删除文档
    参数: query 筛选条件
           multi  默认True表示删除所有符合条件的
                  False只删除一条
     
    索引操作:
    ensure_index()   创建索引
    list_indexes()   查看索引
    drop_index()   删除一个索引
    drop_indexes()  删除所有索引
     
    聚合操作:
    aggregate([])
    参数和mongoshell一样
    返回值和find()函数一样也是得到一个游标对象
     
     
    pymongo进行文件存取操作:
     
    GridFS 文件提取:
     
    import  gridfs
    1. 连接数据库,获取相应的数据库对象
    2. 通过 gridfs.GridFS(db) 获取集合对象(代表存储文件的两个集合)
    3. 通过find()查找文件返回游标
    4. 通过循环遍历游标获取指定文件对象,read()读取文件内容写入本地
     
    以二进制的方式存取文件
    import bson.binary
     
     
    增删改查操作:
     

    from pymongo import MongoClient 
    
    #创建连接
    conn = MongoClient('localhost',27017)
    
    #创建数据库对象
    db = conn.stu 
    
    #创建集合对象
    myset = db.class4 
    
    print(dir(myset))
    
    # 插入操作
    myset.insert({'name':'张铁林','King':'乾隆'})
    myset.insert([{'name':'张国立','King':'康熙'},
        {'name':'陈道明','King':'康熙'}])
    myset.insert_many([{'name':'唐国强','King':'雍正'},
        {'name':'陈建斌','King':'雍正'}])
    myset.insert_one({'name':'郑少秋','King':'乾隆'})
    myset.save({'_id':1,'name':'聂远','King':'乾隆'}) 
    
    # 查找操作
    
    cursor = myset.find({},{'_id':0})
    
    # i为每个文档对应的字典
    for i in cursor:
        print(i['name'],'--->',i['King'])
    
    myset = db.class1 
    # 操作符使用引号变为字符串
    cursor = myset.find({'age':{'$gt':30}},{'_id':0})
    
    cursor.limit(2)#获取前两个文档
    cursor.skip(2) #跳过前两个
    cursor.sort([('age',-1),('name',1)]) #对游标内容排序
    
    for i in cursor:
        print(i)
    print(cursor.next()) #获取下一个文档
    
    
    dic = {'$or':[{'age':{'$gt':35}},{'gender':'w'}]}
    data = myset.find_one(dic,{'_id':0})
    print(data)
    
    # 修改操作
    myset.update({'name':'张国立'},
        {'$set':{'king_name':'玄烨'}})
    
    myset.update({'name':'霍建华'},{'$set':{'King':'乾隆'}},
        upsert = True)
    
    myset.update({'King':'乾隆'},
        {'$set':{'king_name':'弘历'}},multi = True)
    
    myset.update_one({'King':'康熙'},
        {'$set':{'king_name':'爱新觉罗玄烨'}})
    
    myset.update_many({'King':'雍正'},
        {'$set':{'king_name':'胤禛'}})
    
    # 删除操作
    
    myset.remove({'King':'康熙'})
    myset.remove({'King':'乾隆'},multi = False)
    
    #查找并删除
    print(myset.find_one_and_delete({'King':'乾隆'}))
    
    
    #关闭连接
    conn.close()
    索引操作:
     

    from pymongo import MongoClient 
    
    #创建连接
    conn = MongoClient('localhost',27017)
    
    #创建数据库对象
    db = conn['stu'] 
    
    myset = db['class1'] 
    
    # 删除所有索引
    myset.drop_indexes()
    
    # 创建索引
    index = myset.ensure_index('name')
    # 创建复合索引
    index = myset.ensure_index([('name',-1),('age',1)])
    print(index)
    
    # 删除一个索引
    myset.drop_index('name_1')
    
    # 创建特殊索引
    index = myset.ensure_index('name',name = "myIndex",
        unique = True,sparse = True)
    
    # 查看集合中的索引
    for i in myset.list_indexes():
        print(i)
    
    myset = db.class4 
    
    l = [
        {'$group':{'_id':'$King','num':{'$sum':1}}},
        {'$match':{'num':{'$gt':1}}}
    ]
    
    cursor = myset.aggregate(l)
    for i in cursor:
        print(i)
    
    conn.close()


     
    文件的存取:

    from pymongo import MongoClient 
    import bson.binary 
    
    conn = MongoClient('localhost',27017)
    db = conn.images 
    myset = db.img 
    
    #存储
    f = open('file.jpg','rb')
    
    #转换为mongodb的二进制数据存储形式
    content = bson.binary.Binary(f.read())
    
    #插入到数据库
    myset.insert({'filename':'file.jpg','data':content})
    
    #提取
    
    data = myset.find_one({'filename':'file.jpg'})
    
    #通过字典获取到数据库内容写入本地
    with open(data['filename'],'wb') as f:
        f.write(data['data'])
    
    conn.close()


     
     
    手动存入文件MongoDB默认创建的文件数据导出:
     

    from pymongo import MongoClient 
    #pymongo绑定的模块
    import gridfs
    
    conn = MongoClient('localhost',27017)
    db = conn.grid 
    
    #获取gridfs对象
    #fs综合了fs.files  fs.chunks两个集合的属性内容
    fs = gridfs.GridFS(db)
    
    #查文档生产游标
    files = fs.find()
    
    #获取每一个文件的对象
    for file in files:
        print(file.filename)
        if file.filename == 'file.jpg':
            with open(file.filename,'wb') as f:
                #从数据库读取出来
                data = file.read()
                #写入本地
                f.write(data)
    
    conn.close()
  • 相关阅读:
    安卓 Context 和 Application的关系
    Android Intent应用
    android launchmode(四种启动模式)应用场景及实例
    返回数据给上一个活动
    Intent传参数
    安卓activity生命周期
    如何将nideshop部署到本地
    navicat链接数据库错误2013
    数据库设计三大范式
    nodejs版本升级
  • 原文地址:https://www.cnblogs.com/ParisGabriel/p/9527093.html
Copyright © 2011-2022 走看看