python post参数传递不成功_四十九:Python操作MongoDB快速入门

9a69d9314b47cdc6a601793b1a289dc3.png

Python操作MongoDB快速入门

本篇文档旨在介绍快速使用Python程序使用PyMongo驱动程序操作MongoDB数据库。

一、前提

1.MongoDB的服务已成功启动

在开始前, 请确保MongoDB的实例已经成功运行,为了简便起见,本人使用的是本机的MongoDB,用的是默认的localhost与端口27017。

在Ubuntu系统上启动MongoDB的实例:

# 查看MongoDB状态$ sudo systemctl status mongodb# 如果没有启动,可以使用下面命令启动$ sudo systemctl start mongodb# 设置开机启动$ sudo systemctl enable mongodb

1.2.确保PyMongo成功安装

在开始前,请确保PyMongo已经被安装,可以在shell窗口输入下面命令安装PyMongo:

$ pip install pymongo

当你在Python shell中输入下面命令不报错时,说明pymongo已安装完好:

>>> import pymongo

二、通过PyMongo的MongoClient创建连接

使用PyMongo操作MongoDB的第一步是创建MongoClient的实例去连接运行的mongod实例:

from pymongo import MongoClient# 下面命令用于连接默认的host和port的mongod实例client = MongoClient()# 也可以指定host和portclient = MongoClient(host='localhost', port=27017)# 也可以通过MongoDB URI格式创建连接client = MongoClient('mongodb://localhost:27017/')

三、获取数据库 (Databases)

一个MongoDB的实例支持运行多个独立的数据库。当使用PyMongo访问MongoDB时,可以在MongoClient实例上使用属性样式访问数据库:

db = client.testdb # testdb为数据库名称

如果MongoDB的数据库名通过属性风格无法访问(比如:test-db), 那么可以使用字典风格的访问方式:

db = client['test-db']

四、获取集合(Collections)

集合是存储在MongoDB中的一组文档,可以看作和关系数据库中表的等价。在PyMongo中获取集合与获取数据库的工作原理相同:

collection = db.test_collection

使用字典风格访问:

collection = db['test_collection']

关于MongoDB中集合(和数据库)的一个重要注意事项是: 它们是延迟创建的——上面的命令都没有在MongoDB服务器上实际执行任何操作。在向集合和数据库中插入第一个文档时,将创建这些集合和数据库。

五、文档(Documents)

MongoDB中的数据使用类JSON样式的文档表示(并存储)。在PyMongo中,我们使用字典来表示文档。例如,可以使用以下字典来表示博客文章:

import datetimepost = {    'author':'Mike',    'text': 'My first blog post! The post is mostly introducing how to use PyMongo to interact with MongoDB',    'tag':['mongodb','python','pymongo'],    'date': datetime.datetime.utcnow()}

注意,文档可以包含基本Python类型(比如日期时间。日期时间实例),它将自动与相应的BSON类型进行转换。

六、插入文档

将一个文档插入到集合中,我们可以使用insert_one()方法:

In [9]: posts = db.posts                                                        In [10]: post_id = posts.insert_one(post).inserted_id                           In [11]: post_id                                                                Out[11]: ObjectId('5f282900d28216c1cebfacd8')

在向集合中插入文档时如果没有指定"_id"键,会默认自动添加一个"_id"。"_id"必须在这个集合中是唯一的。

在插入第一个文档之后,posts集合实际上已经在服务器上创建了。我们可以通过列出数据库中的所有集合来验证这一点:

In [12]: db.list_collection_names()                                             Out[12]: ['posts']

七、使用find_one()获取一个文档

MongoDB中可以执行的最基本的查询类型是find_one()。此方法返回与查询匹配的单个文档(如果没有匹配项,则返回无)。当您知道只有一个匹配的文档,或者只对第一个匹配的文档感兴趣时,它非常有用。这里我们使用find_one()从posts集合获取第一个文档:

In [13]: db.posts.find_one()                                                    Out[13]: {'_id': ObjectId('5f282900d28216c1cebfacd8'), 'author': 'Mike', 'text': 'My first blog post! The post is mostly introducing how to use PyMongo to interact with MongoDB', 'tag': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2020, 8, 3, 15, 10, 1, 40000)}

如果我们查询一个不存在的author,比如“Eliot”,我们不会得到任何结果:

In [17]: db.posts.find_one({"author":"Eliot"})                                  In [18]:    

八、通过ObjectId查询

可以通过"_id"查询一个post:

In [20]: import pprint                                                          In [21]: post_id                                                                Out[21]: ObjectId('5f282900d28216c1cebfacd8')In [22]: pprint.pprint(posts.find_one({"_id":post_id}))                         {'_id': ObjectId('5f282900d28216c1cebfacd8'), 'author': 'Mike', 'date': datetime.datetime(2020, 8, 3, 15, 10, 1, 40000), 'tag': ['mongodb', 'python', 'pymongo'], 'text': 'My first blog post! The post is mostly introducing how to use '         'PyMongo to interact with MongoDB'}

请注意,ObjectId与其字符串表示形式不同:

In [23]: type(post_id)
Out[23]: bson.objectid.ObjectId
In [24]: post_id_as_str = str(post_id)
In [26]: posts.find_one({"_id":post_id_as_str}) # 没有结果返回
...:

web应用程序中的一个常见任务是从请求URL获取ObjectId并找到匹配的文档。在这种情况下,有必要在调用find_one()方法时传递字符串前将其转换成ObjectId:

In [29]: from bson.objectid import ObjectId     ...:      ...: # web应用从URL中获取post_id并以字符串形式传递     ...: def get(post_id):     ...:     # 从字符串转换成ObjectId     ...:     document = client.posts.find_one({'_id':ObjectId(post_id)}) 

关于Unicode字符串

您可能注意到,从服务器检索时,我们先前存储的常规Python字符串看起来不同(例如,u'Mike'而不是'Mike')。一个简短的解释是合理的。

MongoDB以BSON格式存储数据。BSON字符串是UTF-8编码的,因此PyMongo必须确保它存储的任何字符串只包含有效的UTF-8数据。常规字符串()将被验证并存储为原样。Unicode字符串()首先编码为UTF-8。我们的示例字符串在python shell中表示为u'Mike'而不是'Mike',原因是PyMongo将每个BSON字符串解码为Python unicode字符串,而不是常规str。

九、批量插入

为了使查询更加有趣,让我们再插入一些文档。除了插入单个文档外,我们还可以执行大容量插入操作,方法是将列表作为第一个参数传递给insert_many()。这将插入列表中的每个文档,只向服务器发送一个命令:

In [29]: 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)}]        ​In [30]: result = db.posts.insert_many(new_posts)                               ​In [31]: result.inserted_ids                                                    Out[31]: [ObjectId('5f283257d28216c1cebfacd9'), ObjectId('5f283257d28216c1cebfacda')]​

关于这个例子,有几个有趣的事情需要注意:

  • insert_many()的结果现在返回两个ObjectId实例,每个插入的文档一个。
  • posts[1]的结构与其它的posts不同(其它posts没有tags),我们添加了一个新字段“title”。这就是我们所说的MongoDB是无模式的。

十、查询多个文档

要获取多个文档作为查询的结果,我们使用find()方法。find()返回一个游标实例,它允许我们迭代所有匹配的文档。例如,我们可以迭代posts集合中的每个文档:

In [32]: for post in db.posts.find():     ...:     pprint.pprint(post)     ...:          ...:                                                                        {'_id': ObjectId('5f282900d28216c1cebfacd8'), 'author': 'Mike', 'date': datetime.datetime(2020, 8, 3, 15, 10, 1, 40000), 'tag': ['mongodb', 'python', 'pymongo'], 'text': 'My first blog post! The post is mostly introducing how to use '         'PyMongo to interact with MongoDB'}{'_id': ObjectId('5f283257d28216c1cebfacd9'), 'author': 'Mike', 'date': datetime.datetime(2009, 11, 12, 11, 14), 'tags': ['bulk', 'insert'], 'text': 'Another post!'}{'_id': ObjectId('5f283257d28216c1cebfacda'), 'author': 'Eliot', 'date': datetime.datetime(2009, 11, 10, 10, 45), 'text': 'and pretty easy too!', 'title': 'MongoDB is fun'}

就像find_one()一样,我们可以向find()传递一个文档来限制返回的结果。这里,我们只得到那些作者是“Mike”的文档:

In [33]: for post in db.posts.find({'author':'Mike'}):     ...:     pprint.pprint(post)     ...:                                                                        {'_id': ObjectId('5f282900d28216c1cebfacd8'), 'author': 'Mike', 'date': datetime.datetime(2020, 8, 3, 15, 10, 1, 40000), 'tag': ['mongodb', 'python', 'pymongo'], 'text': 'My first blog post! The post is mostly introducing how to use '         'PyMongo to interact with MongoDB'}{'_id': ObjectId('5f283257d28216c1cebfacd9'), 'author': 'Mike', 'date': datetime.datetime(2009, 11, 12, 11, 14), 'tags': ['bulk', 'insert'], 'text': 'Another post!'}

十一、文档计数

如果我们只想知道有多少文档与一个查询匹配,我们可以执行estimated_document_count()操作,而不是执行完整的查询。我们可以获得集合中所有文档的计数:

In [38]: db.posts.estimated_document_count()                                    Out[38]: 3    # 或者, 注:{}不能省略In [41]: db.posts.count_documents({})                                           Out[41]: 3

如果是有条件的查询:

In [42]: db.posts.count_documents({'author':'Mike'})                            Out[42]: 2

注:老版本通过db.collection.count(),现在在新版本中已过时,建议使用上面两种方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值