MongoDB与python交互

作者: 一只写程序的猿 | 来源:发表于2017-08-22 15:15 被阅读506次

    上一篇文章已经运用了Pymongo这个包,本篇文章详细介绍下Pymongo的使用

    1.Pymongo

    PyMongo是Mongodb的Python接口开发包,是使用python和Mongodb的推荐方式。

    官方文档

    2.安装

    进入虚拟环境
    sudo pip install pymongo
    或源码安装
    python setup.py
    

    3.使用

    • 导入模块
    import pymongo 
    #或者
    from pymongo import MongoClient
    
    • 建立于MongoClient 的连接:
    client = MongoClient('localhost', 27017) 
    # 或者 
    client = MongoClient('mongodb://localhost:27017/') 
    
    • 得到数据库
    db = client.test_database
    # 或者 
    db = client['test-database'] 
    
    • 得到一个数据集合
    collection = db.test_collection
    # 或者 
    collection = db['test-collection'] 
    
    • MongoDB中的数据使用的是类似Json风格的文档
    >>> import datetime 
    >>> post = {"author": "Mike",    
                "text": "My first blog post!",    
                "tags": ["mongodb", "python", "pymongo"], 
                "date": datetime.datetime.utcnow()} 
    
    • 插入一个文档
    >>> posts = db.posts 
    >>> post_id = posts.insert_one(post).inserted_id 
    >>> post_id 
    ObjectId('...') 
    
    • 查找一条数据
    >>> posts.find_one() 
    {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}   
    >>> posts.find_one({"author": "Mike"}) 
    {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}   
    >>> posts.find_one({"author": "Eliot"}) 
    >>> 
    
    • 通过ObjectId来查找
    >>> post_id ObjectId(...) 
    >>> posts.find_one({"_id": post_id})
    {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']} 
    
    • 不要转化ObjectId的类型为String
    >>> post_id_as_str = str(post_id) 
    >>> posts.find_one({"_id": post_id_as_str}) # No result 
    >>> 
    
    • 如果post_id是字符串
    from bson.objectid import ObjectId  
    # The web framework gets post_id from the URL and passes it as a string def get(post_id):   
        # Convert from string to ObjectId:   
        document = client.db.collection.find_one({'_id': ObjectId(post_id)}) 
    
    • 多条插入
    >>> new_posts = [{"author": "Mike", 
                      "text": "Another post!", 
                      "tags": ["bulk", "insert"], 
                      "date": datetime.datetime(2009, 11, 12, 11, 14)}, 
                      {"author": "Eliot", 
                      "title": "MongoDB is fun", 
                      "text": "and pretty easy too!", 
                      "date": datetime.datetime(2009, 11, 10, 10, 45)}] 
    >>> result = posts.insert_many(new_posts) 
    >>> result.inserted_ids 
    [ObjectId('...'), ObjectId('...')] 
    
    • 查找多条数据
    >>> for post in posts.find(): 
    ...  post 
    ... 
    {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']} 
    {u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']} 
    {u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'} 
    
    #查找多个文档2
    cur=stu.find()
    cur.next()
    
    • 获取集合的数据条数
    posts.count() 
    
    #满足某种查找条件的数据条数:
    posts.find({"author": "Mike"}).count() 
    
    • 范围查找
    #比如说时间范围
    >>> d = datetime.datetime(2009, 11, 12, 12) 
    >>> for post in posts.find({"date": {"$lt": d}}).sort("author"): 
    ...  print post 
    {u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'} 
    {u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']} 
    

    4.mongoDB其它操作

    1.超级管理员

    • 为了更安全的访问mongodb,需要访问者提供用户名和密码,于是需要在mongodb中创建用户
      采用了角色-用户-数据库的安全管理方式
      常用系统角色如下:

    root:只在admin数据库中可用,超级账号,超级权限
    Read:允许用户读取指定数据库
    readWrite:允许用户读写指定数据库

    • 创建超级管理用户
    use admin
    db.createUser({
        user:'admin',
        pwd:'123',
        roles:[{role:'root',db:'admin'}]
    })
    
    • 添加访问用户
    mongo进入操作界面
    
    use admin   # 指定数据库
    
    db.addUser(“用户名”, “密码”) 添加用户    # 可以使用,已经提示过时
    
    db.createUser(“用户名”, “密码”) 添加用户
    
    
    • 启用安全认证
      修改配置文件
    sudo vi /etc/mongod.conf
    
    • 启用身份验证
      注意:keys and values之间一定要加空格, 否则解析会报错
    security:
      authorization: enabled
    
    • 重启服务
    sudo service mongod stop
    sudo service mongod start
    
    • 终端连接
     mongo -u 'admin' -p '123' --authenticationDatabase 'admin'
    
    • 普通用户管理
      使用超级管理员登录,然后进入用户管理操作
      查看当前数据库的用户
    use test1
    show users
    
    • 创建普通用户
    db.createUser({
        user:'t1',
        pwd:'123',
        roles:[{role:'readWrite',db:'test1'}]
    })
    
    • 终端连接
    mongo -u t1 -p 123 --authenticationDatabase test1
    
    • 切换数据库,执行命令查看效果
      修改用户:可以修改pwd、roles属性
    db.updateUser('t1',{pwd:'456'})
    

    2.主从双备

    复制的优点

    • 复制提供了数据的冗余备份,并在多个服务器上存储数据副本,提高了数据的可用性,并可以保证数据的安全性
    • 复制还允许从硬件故障和服务中断中恢复数据
    • 数据备份
    • 数据灾难恢复
    • 读写分离
    • 高(24* 7)数据可用性
    • 无宕机维护
    • 副本集对应用程序是透明
    • 复制的工作原理
    • 复制至少需要两个节点A、B...
    • A是主节点,负责处理客户端请求
    • 其余的都是从节点,负责复制主节点上的数据
    • 节点常见的搭配方式为:一主一从、一主多从
    • 主节点记录在其上的所有操作,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致
    • 主节点与从节点进行数据交互保障数据的一致性
    • 复制的特点
    • N 个节点的集群
    • 任何节点可作为主节点
    • 所有写入操作都在主节点上
    • 自动故障转移
    • 自动恢复

    案例:

    • step1:创建数据库目录t1、t2
      在Desktop目录下演示,其它目录也可以,注意权限即可
    mkdir t1
    mkdir t2
    
    • step2:使用如下格式启动mongod,注意replSet的名称是一致的
    mongod --bind_ip 192.168.10.110 --port 27018 --dbpath ~/Desktop/t1 -->replSet rs0
    mongod --bind_ip 192.168.10.111 --port 27019 --dbpath ~/Desktop/t2 -->replSet rs0
    
    • step3:连接主服务器,此处设置192.168.10.110:27018为主服务器
    mongo --host 192.168.10.110 --port 27018
    
    • step4:初始化
    rs.initiate()
    
    • step5:查看当前状态
    rs.status()
    
    • step6:添加复本集
    rs.add('192.168.10.111:27019')
    
    • step8:新开窗口,连接第二个mongo服务
    mongo --host 192.168.10.111 --port 27019
    
    • step9:向主服务器中插入数据
    use test1
    for(i=0;i<10;i++){db.t1.insert({_id:i})}
    db.t1.find()
    
    • step10:在从服务器中插查询
      说明:如果在从服务器上进行读操作,需要设置rs.slaveOk()
    rs.slaveOk()
    db.t1.find()
    
    • 其它说明
      删除从节点
    rs.remove('192.168.10.111:27019')
    

    关闭主服务器后,再重新启动,会发现原来的从服务器变为了主服务器,新启动的服务器(原来的从服务器)变为了从服务器

    3.备份

    • 语法
    mongodump -h dbhost -d dbname -o dbdirectory
    
    #例
    sudo mkdir test1bak
    sudo mongodump -h 192.168.10.110:27017 -d test1 -o ~/flex/test1bak
    
    • -h:服务器地址,也可以指定端口号
    • -d:需要备份的数据库名称
    • -o:备份的数据存放位置,此目录中存放着备份出来的数据

    4.恢复

    • 语法
    mongorestore -h dbhost -d dbname --dir dbdirectory
    
    #例
    mongorestore -h 192.168.10.110:27017 -d test2 --dir ~/flex/test1bak/test1
    
    • -h:服务器地址
    • -d:需要恢复的数据库实例
    • -dir:备份数据所在位置

    5.Mongodb与python交互

    • 之前学习了爬虫,现在我们把爬取得到的数据存储于Mongodb中
    #爬取英雄联盟英雄信息详情,并存储
    
    #-*- coding:utf-8 -*-
    import pymongo
    import requests
    from bs4 import BeautifulSoup
    
    #建立于MongoClient 的连接
    client = pymongo.MongoClient('localhost',27017)
    #得到数据库
    hero = client['hero']
    #得到一个数据集合
    sheet_tab = hero['sheet_tab']
    url = 'http://lol.duowan.com/hero/'
    req = requests.get(url)
    soup = BeautifulSoup(req.text,'html.parser')
    links = soup.find(id="champion_list").find_all('a')
    for link in links:
        link = link['href']
        requ = requests.get(link)
        sop = BeautifulSoup(requ.text,'html.parser')
        data = {
        'title' : sop.find('h2',class_="hero-title").get_text(),
        'name' : sop.find('h1',class_="hero-name").get_text(),
        'tags' : sop.find('div',class_="hero-box ext-attr").find_all('span')[1].get_text(),
        'story' : sop.find('div',class_="hero-popup").find_all('p')[0].get_text(),
        }
        sheet_tab.insert_one(data)
    
    • 开启mongo,运行代码
    通过Robo 3T可视化工具我们可以看到抓取到了137条数据,并且已存储到mongodb中

    6.完成命令行项目:学生信息管理(基于Python2.7)

    • 代码操作
    #-*- coding:utf-8 -*-
    import pymongo
    
    def system():
        print('◆您将进入数据库管理系统,数据无价、谨慎操作!◆')
        print('◇1:查看数据◇')
        print('◇2:增加数据◇')
        print('◇3:修改数据◇')
        print('◇4:删除数据◇')
        print('◇5:搜索数据◇')
        print('●6:退出数据库管理系统●')
    
        # 建立与mongodb的连接
        client = pymongo.MongoClient('localhost', 27017)
        # 得到数据库
        stu = client['stu']
        # 得到一个数据集合
        message = stu['message']
    
        while True:
            order = int(raw_input('请输入相关指令:'))
            if order==1:
                exit = message.count()
                if exit==0:
                    print('抱歉,数据库中目前没有相关数据!')
                else:
                    for data in message.find():
                        content = data['name']+data['age']+data['sex']
                        print(content)
            elif order ==2:
                name = raw_input('请输入学生姓名:')
                age = raw_input('请输入学生年龄:')
                sex = raw_input('请输入学生性别(男/女):')
                data = {
                    'name':name,
                    'age':age,
                    'sex':sex,
                }
                message.insert_one(data)
                print ('添加成功!')
    
            elif order == 3:
                name = raw_input('请输入要修改的学生姓名:')
                exit = message.count({'name': name})
                if exit != 0:
                    age = raw_input('请输入修改后的学生年龄:')
                    message.update({'name':name},{'$set':{'age':age}})
                    print('修改成功')
                else:
                    print '抱歉,数据库中没有这个学生的信息!'
    
            elif order == 4:
                name = raw_input('请输入要删除的学生姓名:')
                exit = message.count({'name': name})
                if exit != 0:
                    message.remove({'name':name})
                    print('删除成功')
                else:
                    print '抱歉,数据库中没有这个学生的信息!'
    
            elif order == 5:
                name = raw_input('请输入要查询的学生姓名:')
                exit = message.count({'name':name})
                if exit!=0:
                    data = message.find_one({'name':name})
                    content = data['name']+data['age']+data['sex']
                    print content
                else:
                    print '抱歉,数据库中没有这个学生的信息!'
    
            elif order == 6:
                print('感谢您的使用!')
                break
            else:
                print('您的输入有误,请输入有效指令(1/2/3/4/5)')
    
    if __name__ == '__main__':
        system()
    
    测试结果

    相关文章

      网友评论

        本文标题:MongoDB与python交互

        本文链接:https://www.haomeiwen.com/subject/cvwkdxtx.html