zoukankan      html  css  js  c++  java
  • 一文说通MongoDB via Python操作

    Python并不仅仅是一个做Machine Learning的语言。

    说到Python,一般都会感觉它关联着ML,如果不是做ML开发,就会觉得离自己很远。而实际上,作为一门语言,Python在应用中跟别的语言没什么区别,甚至在某些时间,它的方便会让人感觉很舒服。

    试想一下,有个小需求,需要临时改一些数据库的数据。怎么搞?直接写数据库脚本?麻烦。开个IDE写段代码?更麻烦。这时候,有Python就很爽了 --- 随便开个Notepad或VIM,写段代码,就搞定了。

    很方便,有没有?

    所以,不管做什么样的开发,了解一点Python,还是有点意义的。

    今天我们就整理一个知识点:Python操作MongoDB数据库。

        为了防止不提供原网址的转载,特在这里加上原文链接:https://www.cnblogs.com/tiger-wang/p/13216977.html

    一、运行准备

    首先,我们需要有Python3 。现在Python全线从v2转为v3,如果还停留在v2的年代,不妨升一下级。

    Python3的安装不详细说,官网在https://www.python.org

    检查是否安装Python3,可以用以下命令:

    % python3 --version
    Python 3.7.4

    如果安装了,会返回Python3的版本号。我装的是3.7.4 。

    Python操作MongoDB数据库,需要PyMongo库的支持。

    % pip install pymongo

    或者

    % python3 -m pip install pymongo

    pip是Python全系的软件包管理工具,类似于Ubuntu/Debian的apt、Centos的rpm、MacOS的brew。

    新安装的Python3,可能没有pip命令。检查一下:

    % pip --version

    同样,如果有安装,会返回pip的版本号。

    如果没有安装,以下是命令:

    % curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
    % python3 get-pip.py

    也可以去pip官网自行查找安装。官网在https://pip.pypa.io/en/stable/

    MongoDB也需要安装好。安装过程在文章15分钟从零开始搭建支持10w+用户的生产环境(二)里有详细的步骤,这儿略过。

    这样,我们就准备好了全部的运行环境。

    二、操作MongoDB

    1. 连接串

    MongoDB的连接串,在所有开发语言中都是一样的:

    database_connection_uri = "mongodb://localhost:27031/admin"

    2. 连接数据库

    PyMongo提供了MongoClient用来连接MongoDB,并初始化对象。

    client = pymongo.MongoClient(database_connection_uri)

    3. 打开数据库和数据集

    db = client["Test"]
    collection = db["TestCollection"]

    这个例子中,数据库叫Test,数据集Collection叫TestCollection

    到这儿,数据集已经正常打开。

    全部的代码如下:

    #!/usr/local/bin python3
    # -*- coding: UTF-8 -*-

    import pymongo

    database_connection_uri = "mongodb://localhost:27031/admin"

    def main():

        client = pymongo.MongoClient(database_connection_uri)
        db = client["Test"]
        collection = db["TestCollection"]

        print("Success !!!")

    if __name__ == '__main__':
        main()

    4. 创建索引

    MongoDB中,索引很关键。一个好的索引可以让上亿级的数据集查询在毫秒内出结果。

    collection.create_index([("article_id", pymongo.ASCENDING)], background=True)

    升序是pymongo.ASCENDING,降序是pymongo.DESCENDING

    看参数就知道,如果创建联合索引,就把字段名一个一个列出来:

    collection.create_index([("article_id", pymongo.ASCENDING), ("action_time", pymongo.DESCENDING)], background=True)

    在MongoDB中,索引可以在任何时候创建。

    5. 创建数据

    PyMongo所有数据采用Json数据。

    Demo数据:

    import datetime

    article1 = {
        "article_id"1,
        "title""文章标题1",
        "body""文章内容1",
        "action_time": datetime.datetime.utcnow()
    }

    直接调用collection对象的insert命令创建数据:

    result = collection.insert(article1)

    创建成功后,会返回该数据文档的_id值。

    看一下全部代码:

    def main():

        client = pymongo.MongoClient(database_connection_uri)
        db = client["Test"]
        collection = db["TestCollection"]

        article1 = {
            "article_id"1,
            "title""文章标题1",
            "body""文章内容1",
            "action_time": datetime.datetime.utcnow()
        }

        result = collection.insert(article1)
        print(result)

    也可以一次创建多条文档:

    result = collection.insert([article1, article2])

    注意那个中括号。

    多条创建时,返回值result也是个列表,里面是所有创建记录的_id值。

    此外,PyMongo还提供了另外两个方法:insert_oneinsert_many,对应创建一条数据和多条数据。

    result = collection.insert_one(article1)
    result = collection.insert_many([article1, article2])

    这两个方法返回值与insert返回值略有不同,返回的是个对象。

    insert_one返回InsertOneResultInsertOneResult.inserted_id才是_id值。

    insert_many返回InsertManyResultInsertManyResult.inserted_ids_id的列表。

    6. 查询数据

    查询数据有两个方法:find_onefind

    先说find_one,看名称就知道,是查一条文档数据,返回结果是一个字典类型的记录。

    result = collection.find_one({"article_id"1})
    print(type(result))
    print(result)

    输出结果:

    <class 'dict'>
    {'_id': ObjectId('5efb1ecc7ca7cd50ed1150ed'), 'article_id': 1, 'title''文章标题1''body''文章内容1''action_time': datetime.datetime(2020, 6, 30, 11, 15, 24, 97000)}

    当然也可以使用_id查询:

    from bson.objectid import ObjectId

    result = collection.find_one({'_id': ObjectId('5efb1ecc7ca7cd50ed1150ed')})

    find方法,用来查询多条数据。

    results = collection.find({"title": {"$ne":""}})
    print(type(results))
    print(results)
    for result in results:
        print(result)

    输出结果:

    <class 'pymongo.cursor.Cursor'>
    <pymongo.cursor.Cursor object at 0x7f82c2cf7d50>
    {'_id': ObjectId('5efb1ecc7ca7cd50ed1150ed'), 'article_id': 1, 'title''文章标题1''body''文章内容1''action_time': datetime.datetime(2020, 6, 30, 11, 15, 24, 97000)}
    {'_id': ObjectId('5efb1ecc7ca7cd50ed1150ee'), 'article_id': 2, 'title''文章标题2''body''文章内容2''action_time': datetime.datetime(2020, 6, 30, 11, 15, 24, 97000)}

    能看出,find查询的结果是一个游标cursor,指向返回的数据集合。数据可以循环读出。

    7. 结果统计

    统计查询结果有多少条数据,PyMongo提供了一个count方法:

    results = collection.find({"title": {"$ne":""}}).count()

    或者查整个数据集的数据:

    results = collection.find().count()

    8. 排序查询

    排序也是一个方法,sort

    results = collection.find({"title": {"$ne":""}}).sort("action_time", pymongo.ASCENDING)

    升序是pymongo.ASCENDING,降序是pymongo.DESCENDING

    9. 偏移和限定

    两个用处不大不小的功能,通常在一起用,当然分开也没关系。

    results = collection.find({"title": {"$ne":""}}).sort("action_time", pymongo.DESCENDING).skip(1).limit(1)

    limit限定了结果集取多少条数据,而skip则决定跳过多少条数据后去取。

    在数据量不大的情况下,可以用来做分页。而如果数据量很大,这种方式效率不高,更好的做法是记住前一个页的最后一条数据的关键值,例如_id,查询时取条件大于这个值的数据。

    10. 更新数据

    PyMongo提供了两个更新数据的方法:update_oneupdate_many。代码是这样的:

    filter = {"article_id"1}
    update = {"$set": {"body""新的文章内容"}}
    result = collection.update_one(filter, update)
    print(type(result))

    返回一个对象UpdateResult,里面包含更新结果的全部信息。

    注意:这儿有个不同于传统SQL的地方,一定要注意。当更新的条件匹配到多条数据时,update_one只会更新匹配到的数据集中第一条数据,update_many可以更新匹配到的全部数据。所以,如果用update_one,除非是你本意,一定要确定条件匹配到的数据唯一。

    11. 删除数据

    也同样有两个方法:delete_onedelete_many。用法和更新相似:

    filter = {"article_id"1}
    result = collection.delete_one(filter)
    print(type(result))

    同样的,delete_one也只会删除匹配到的数据集中第一条数据。

    11. 原子级处理

    这是MongoDB中的一个特色操作,也是早期MongoDB的无奈之选。因为早期版本的MongoDB并不支持事务处理。而上面讲到的更新和删除,并不能保证并发情况下的数据安全。

    MongoDB为了解决这个并发的数据问题,增加了三个原子级的处理,对应于PyMongo的三个方法:find_one_and_updatefind_one_and_replacefind_one_and_delete

    这三个方法,看名字就知道做什么的。用法上,跟上面的更新和删除一致,区别在于:这三个方法执行的时候,会通过数据锁来保证数据修改在并发状态下的一致性。当然,这个处理是有一定代价的,它要比上面说的更新和删除慢一点,实测数据会慢5毫秒左右。

    这三个方法应用挺广的。比方我们需要生成一个自增量ID,就可以用find_one_and_update来控制增量数据,因为他是原子级操作,所以并发也不会有重复的数据产生。

    嗯,MongoDB从4.0开始,已经全面支持事务了。不过,这三个方法依然保留了下来。

    12. 事务

    这是一个新特性,需要数据库4.0以上才支持。写法上,跟传统的事务没什么区别。

    with client.start_session() as s:
        s.start_transaction()

        filter = {"article_id"1}
        update = {"$set": {"body""新的文章内容"}}
        result = collection.update_one(filter, update)

        result = collection.delete_one(filter)

        s.commit_transaction()

    以上部分,就是Python操作MongoDB的全部内容。

    最后,送大家一个彩蛋。

    三、彩蛋

    有时候,我们需要把写好的Python程序给到别人来使用,可是,我们又不能让别人也装个Python。怎么办?

    神器来了。

    PyInstaller,官网在http://www.pyinstaller.org

    它的作用,是把您写的Python程序,转成各种操作系统下的可执行文件。

    PyInstaller安装很简单:

    % pip install pyinstaller

    使用更简单:

    % pyinstaller your_code.py

    经过一翻编译,会生成几个目录。其中,dist目录下,就是编译完成的可执行程序。当然,我们的Python程序会引用或依赖一些库,而可爱的PyInstaller,也很贴心的把这些库复制到了这个目录中。

    找到目录中同名的可执行程序,例如这个例子中,将是your_code,运行之,搞定。

    (全文完)

    本文的配套代码,在https://github.com/humornif/Demo-Code/tree/master/0016

     


    微信公众号:老王Plus

    扫描二维码,关注个人公众号,可以第一时间得到最新的个人文章和内容推送

    本文版权归作者所有,转载请保留此声明和原文链接

  • 相关阅读:
    RedHat Linux-配置YUM仓库
    04、管道符、重定向与环境变量
    03、新手必须掌握的Linux命令
    size_t
    decltype关键字
    python numpy使用笔记
    Huffman编码
    动态规划(dynamic programming)
    Prim算法
    Kruskal算法
  • 原文地址:https://www.cnblogs.com/tiger-wang/p/13216977.html
Copyright © 2011-2022 走看看