这是本人翻译的PyMongo官方文档。如今网上分(抄)享(袭)的PyMongo博客文章不少,一方面这些文章本就是抄袭的,谈不上什么格式美观,另外一方面其实这些博客已经落后好久了,根本是不能做为参考的。遂本身翻译了一下。渣翻译请见谅,能看懂就行。
本翻译文档包含如下内容:html
- 使用PyMongo插入数据
- 使用PyMongo查询数据
- 使用PyMongo更新数据
- 使用PyMongo删除数据
- 使用PyMongo进行数据聚合
- 使用PyMongo建立索引
原文地址见连接:原文地址python
PyMongo是一个用于MongoDB的Python工具,也是一个被推荐的Python操做MongoDB数据库的方式。linux
你能够只用pip工具安装:mongodb
pip install pymongo
使用Windows安装工具,详见https://pypi.python.org/pypi/pymongo/。shell
在一个Python交互shell中完成此过程,或者也能够在其余Python环境中完成,例如Python脚本、Python模块、Python项目。数据库
从pymongo中引入MongoClicent。windows
from pymongo import MongoClient
使用MongoClient建立一个链接:api
client = MongoClient()
若是你没有特别为MongoClient指定参数,MongoClient将使用MongoDB默认参数即localhost接口和27017端口。数组
你可使用一个完整的MongoDB URI来定义链接:app
client = MongoClient("mongodb://mongodb0.example.net:27019")
这个MongoClient表明了一个运行于mongodb.example.net端口号为27019的MongoDB链接。
第一个你用pymongo来交互的基本类是Database
,它表明了MongoDB中的数据库(database)结构。数据库保存了逻辑上相关的集合组。MongoDB将在第一次使用新的数据库的时候自动建立它。
你可使用属性访问的方式,赋值一个数据库(例如名字为primer
)给本地变量db
,以下所示:
db = client.primer
你也可使用字典形式访问一个数据库,这会移除Python特有的命名限制,以下所示:
db = client['primer']
第二个你将使用pymongo进行交互的基本类是Collection
,它表明了MongoDB中的集合(collection)结构。集合(collection)保存了逻辑上相关的文档组。
你能够直接使用字典形式访问集合或者经过一个访问一个数据库对象的属性来访问集合,以下所示:
db.dataset db['dataset']
你也能够给一个变量进行赋值,以在其余地方使用这个集合,以下所示:
coll = db.dataset coll = db['dataset']
你可使用insert_one()
方法和insert_many()
方法来向MongoDB的集合中插入文档。若是你所插入的集合在MongoDB中不存在,MongoDB将为你自动建立一个集合。
在Python命令行或者IDLE中,使用MongoClient链接一个正在运行的MongoDB实例,且已经打开test
数据库。
from pymongo import MongoClient client = MongoClient() db = client.test
向集合restaurants
中插入一个文档。若是集合不存在,这个操做将建立一个新的集合。
from datetime import datetime result = db.restaurants.insert_one( { "address": { "street": "2 Avenue", "zipcode": "10075", "building": "1480", "coord": [-73.9557413, 40.7720266] }, "borough": "Manhattan", "cuisine": "Italian", "grades": [ { "date": datetime.strptime("2014-10-01", "%Y-%m-%d"), "grade": "A", "score": 11 }, { "date": datetime.strptime("2014-01-16", "%Y-%m-%d"), "grade": "B", "score": 17 } ], "name": "Vella", "restaurant_id": "41704620" } )
这个操做返回了一个InsertOneResult对象,它包括了insert_id
属性表示被插入的文档的_id
。访问insert_id
的方式以下:
result.inserted_id
你插入的文档的ObjectId将和以下所示的不一样。
ObjectId("54c1478ec2341ddf130f62b7")
若是你传递给insert_one()
方法的参数不包含_id
字段,MongoClient将自动添加这个字段而且生成一个ObjectId设置为这个字段的值。
你能够经过find()
方法产生一个查询来从MongoDB的集合中查询到数据。MongoDB中全部的查询条件在一个集合中都有一个范围。
查询能够返回在集合中的全部数据或者只返回符合筛选条件(filter)或者标准(criteria)的文档。你能够在文档中指定过滤器或者标准,并做为参数传递给find()
方法。
find()
方法返回一个查询结果的游标,这是一个产生文档的迭代对象。
本示例中使用test
数据库中的restaurants
集合。与使用示例数据填充集合有关的介绍请见Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient链接一个正在运行的MongoDB实例,且已经打开test
数据库。
from pymongo import MongoClient client = MongoClient() db = client.test
调用find()
方式不须要传值便可获得集合中全部的文档。举例来讲,以下所示的操做便是返回restaurants
集合中全部文档。
cursor = db.restaurants.find()
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果包含了全部restaurants
集合中的全部文档。
对某一个字段的相等条件查询有以下形式:
{ <field1>: <value1>, <field2>: <value2>, ... }
若是字段(<field>
)在某个文档的某一个数组内,则使用点操做符(dot notation)去访问该字段。
以下所示的操做将查询borough
字段等于Manhattan
的文档。
cursor = db.restaurants.find({"borough": "Manhattan"})
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将只包含符合条件的文档。
要指定嵌入文档中的字段的查询条件,须要使用点操做符。使用点操做符须要使用双引号将字段名包裹。下面的操做将指定一个文档的地址字典中的邮编字段的一个相等的条件。
cursor = db.restaurants.find({"address.zipcode": "10075"})
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将只包含符合条件的文档。
更多的关于嵌入式文档的查询条件信息,请参阅Embedded Documents。
grades
数组包含一个嵌入式文档做为其元素。在该文档的字段上指定一个相等条件须要用到点操做符。使用点操做符须要使用双引号将字段名包裹。以下所示的查询将查询一个有嵌入式文档的grades
字段,该字段中的grade
等于B
。
cursor = db.restaurants.find({"grades.grade": "B"})
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将只包含符合条件的文档。
更多的关于数组内查询条件的信息,例如数组中特殊的混合条件,请参阅Array及$elemMatch操做符。
MongoDB支持使用操做符指定查询条件,例如比较操做符。虽然这其中有一些例外,例如$or
和$and
条件操做符。使用操做符进行查询通常有以下形式:
{ <field1>: { <operator1>: <value1> } }
完整的操做符列表请查阅query opeartors
(http://docs.mongodb.org/manual/reference/operator/query)。
查询字段grades
包含一个嵌入式文档,其中score
大于30。
cursor = db.restaurants.find({"grades.score": {"$gt": 30}})
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将只包含符合条件的文档。
查询字段grades
包含一个嵌入式文档,其中score
小于10。
cursor = db.restaurants.find({"grades.score": {"$lt": 10}})
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将只包含符合条件的文档。
你可使用逻辑与(AND)或者逻辑或(OR)组合多个查询条件。
你可使用一个列表指定一个逻辑与条件查询操做,使用逗号分隔条件。
cursor = db.restaurants.find({"cuisine": "Italian", "address.zipcode": "10075"})
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将只包含符合条件的文档。
你可使用$or
操做符进行逻辑或条件的指定。
cursor = db.restaurants.find( {"$or": [{"cuisine": "Italian"}, {"address.zipcode": "10075"}]})
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将只包含符合条件的文档。
要指定结果集的顺序,能够经过追加sort()
方法进行查询。给sort()
方法传递须要排序的字段和配需类型等。
pymongo.ASCENDING
表示升序排序。pymongo.DESCENDING
表示降序排序。若是要经过多个键星星排序,能够传递键的列表和以及对应的排序类型的列表。举例来讲,以下操做将返回restaurants
集合中全部的文档,而且先经过borough
字段进行升序排序,而后在每一个borough
内,经过"address.zipcode"
字段进行升序排序。
import pymongo cursor = db.restaurants.find().sort([ ("borough", pymongo.ASCENDING), ("address.zipcode", pymongo.ASCENDING) ])
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将只包含符合条件且通过排序的文档。
你可使用update_one()
和update_many
方法更新集合中的文档。update_one()
方法一次更新一个文档。使用update_many()
方法能够更新全部符合条件的文档。方法接受如下三个参数:
要指定更新时的过滤器,使用和查询条件时相同的结构便可。参见使用PyMongo查询数据获取查询条件的信息。
你不能更新_id
字段。
本示例中使用test
数据库中的restaurants
集合。与使用示例数据填充集合有关的介绍请见Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient链接一个正在运行的MongoDB实例,且已经打开test
数据库。
from pymongo import MongoClient client = MongoClient() db = client.test
要改变一个特定字段的值,MongoDB提供了更新操做符,例如$set
操做符能够修改值。例如$set
之类的操做符将在没有该字段的时候新建这个字段。能够查阅update operators做为参考。
以下操做将更新第一个符合name
等于Juni
这个条件的文档。使用$set
操做符更新cuisine
字段且将lastModified
修改成当前日期。
result = db.restaurants.update_one( {"name": "Juni"}, { "$set": { "cuisine": "American (New)" }, "$currentDate": {"lastModified": True} } )
这个操做返回了一个UpdateResult对象。这个对象报告了符合条件的文档数目以及被修改的文档数目。
要查看符合筛选器条件的文档数目,经过访问UpdateResult
对象的matched_count
属性。
result.matched_count
matched_count
值为:
1
要查看更新操做中被修改的文档数目,经过访问UpdateResult
对象的modified_count
属性。
modified_count
值为:
1
要更新一个嵌入式文档中的字段,须要使用点操做符。当使用点操做符时,使用点操做符须要使用双引号将字段名包裹。下面的操做将更新address
字段中的street
值。
result = db.restaurants.update_one( {"restaurant_id": "41156888"}, {"$set": {"address.street": "East 31st Street"}} )
这个操做返回了一个UpdateResult
对象。这个对象报告了符合条件的文档数目以及被修改的文档数目。
要查看符合筛选器条件的文档数目,经过访问UpdateResult
对象的matched_count
属性。
result.matched_count
matched_count
值为:
1
要查看更新操做中被修改的文档数目,经过访问UpdateResult
对象的modified_count
属性。
modified_count
值为:
1
update_one()
方法更新了一个文档,要更新多个文档,须要使用update_many()
方法。下面的操做将更新全部的address.zipcode
等于10016
以及cuisine
等于Other
的文档,将cuisine
字段设置为Category To Be Determined
以及将lastModified
更新为当前日期。
result = db.restaurants.update_many( {"address.zipcode": "10016", "cuisine": "Other"}, { "$set": {"cuisine": "Category To Be Determined"}, "$currentDate": {"lastModified": True} } )
这个操做返回了一个UpdateResult
对象。这个对象报告了符合条件的文档数目以及被修改的文档数目。
要查看符合筛选器条件的文档数目,经过访问UpdateResult
对象的matched_count
属性。
result.matched_count
matched_count
值为:
20
要查看更新操做中被修改的文档数目,经过访问UpdateResult
对象的modified_count
属性。
modified_count
值为:
20
要替换整个文档(除了_id
字段),将一个完整的文档做为第二个参数传给update()
方法。替代文档对应原来的文档能够有不一样的字段。在替代文档中,你能够忽略_id
字段由于它是不变的。若是你包含了_id
字段,那它必须和原文档的值相同。
重要:
在更新以后,该文档将只包含替代文档的字段。
在以下的更新操做后,被修改的文档将只剩下_id
、name
和address
字段。该文档将再也不包含restaurant_id
、cuisine
、grades
以及borough
字段。
result = db.restaurants.replace_one( {"restaurant_id": "41704620"}, { "name": "Vella 2", "address": { "coord": [-73.9557413, 40.7720266], "building": "1480", "street": "2 Avenue", "zipcode": "10075" } } )
replace_one
操做返回了一个UpdateResult
对象。这个对象报告了符合条件的文档数目以及被修改的文档数目。
要查看符合筛选器条件的文档数目,经过访问UpdateResult
对象的matched_count
属性。
result.matched_count
matched_count
值为:
20
要查看更新操做中被修改的文档数目,经过访问UpdateResult
对象的modified_count
属性。
modified_count
值为:
20
你可使用delete_one()
以及delete_many()
方法从集合中删除文档。方法须要一个条件来肯定须要删除的文档。
要指定一个删除条件,使用和查询条件时相同的结构便可。参见使用PyMongo查询数据获取查询条件的信息。
本示例中使用test
数据库中的restaurants
集合。与使用示例数据填充集合有关的介绍请见Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient链接一个正在运行的MongoDB实例,且已经打开test
数据库。
from pymongo import MongoClient client = MongoClient() db = client.test
下面的操做将删除全部复合条件的文档。
result = db.restaurants.delete_many({"borough": "Manhattan"})
这个操做返回了一个DeleteResult对象。这个对象报告了被删除的文档数目。
要查看被删除的文档数目,经过访问DeleteResult
对象的deleted_count
属性。
result.deleted_count
deleted_count
值为:
10259
若是你已经插入或者更新了文档,那么你获得的结果将和示例不一样。
要删除一个集合中的全部文档,给delete_many()
方法传递一个空的条件参数便可。
result = db.restaurants.delete_many({})
这个操做返回了一个DeleteResult对象。这个对象报告了被删除的文档数目。
要查看被删除的文档数目,经过访问DeleteResult
对象的deleted_count
属性。
result.deleted_count
deleted_count
值为:
15100
若是你已经插入或者更新了文档,那么你获得的结果将和示例不一样。
删除全部文档的操做只会清空集合中的文档。该集合以及集合的索引将依旧存在。要清空一个集合,销毁该集合以及它的索引而且重建集合和索引多是相比于清空一个集合更加高效的操做方式。使用drop()
方法能够销毁一个集合,包括它全部的索引。
db.restaurants.drop()
MongoDB能够进行数据聚合操做,例如能够针对某一字段进行分组或者对某一字段不一样的值进行统计。
使用aggregate()
方法可使用基于步骤的聚合操做。appregate()
方法接受多个数组做为每一步的操做。每个阶段按照顺序处理,描述了对数据操做的步骤。
db.collection.aggregate([<stage1>, <stage2>, ...])
这部分的例子使用了test
数据库中的restaurants
集合。须要查看在集合中填充的实例数据,请参阅Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient链接一个正在运行的MongoDB实例,且已经打开test
数据库。
from pymongo import MongoClient client = MongoClient() db = client.test
使用$group
操做符去利用一个指定的键进行分组。在$group
操做中,指定须要分组的字段为_id
。$group
经过字段路径访问字段,该字段须要有一个美圆符号$
做为前缀。$group
操做可使用累加器对本次分组进行计算。下面的例子将使用borough
字段对restaurants
集合进行操做,而且使用$sum
累加器进行文档的统计计算。
cursor = db.restaurants.aggregate( [ {"$group": {"_id": "$borough", "count": {"$sum": 1}}} ] )
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将由以下文档组成:
{u'count': 969, u'_id': u'Staten Island'} {u'count': 6086, u'_id': u'Brooklyn'} {u'count': 10259, u'_id': u'Manhattan'} {u'count': 5656, u'_id': u'Queens'} {u'count': 2338, u'_id': u'Bronx'} {u'count': 51, u'_id': u'Missing'}
_id
字段包含了不一样的borough
值,即根据键的值进行了分组。
使用$match
操做来删选文档。$match
使用MongoDB查询语法。下面的管道使用$match
来对restaurants
进行一个borough
等于"Queens"
且cuisine
等于Brazilian
的查询。接着$group
操做对命中的文档使用address.zipcode
字段分组并使用$sum
进行统计。$group
经过字段路径访问字段,该字段须要有一个美圆符号$
做为前缀。
cursor = db.restaurants.aggregate( [ {"$match": {"borough": "Queens", "cuisine": "Brazilian"}}, {"$group": {"_id": "$address.zipcode", "count": {"$sum": 1}}} ] )
迭代游标(cursor)而且打印文档内容。
for document in cursor: print(document)
结果将由以下文档组成:
{u'count': 1, u'_id': u'11368'} {u'count': 3, u'_id': u'11106'} {u'count': 1, u'_id': u'11377'} {u'count': 1, u'_id': u'11103'} {u'count': 2, u'_id': u'11101'}
_id
字段包含了不一样的zipcode
值,即根据键的值进行了分组。
索引能够对查询的高效执行起到支持。若是没有索引,MongoDB必须进行全表扫描,即扫描集合中的每一个文档,来选择符合查询条件的文档。若是一个适当的索引存在于一个查询中,MongoDB可使用索引限制必须检查文档的数量。
使用create_index()
方法来为一个集合建立索引。因此能够对查询的高效执行起到支持。MongoDB会在建立文档的时候自动为_id
字段建立索引。
要为一个或多个字段建立索引,使用一个包含字段和索引类型的列表做为参数:
[ ( <field1>: <type1> ), ... ]
pymongo.ASCENDING
为索引类型(
pymongo.DESCENDING
为索引类型(
create_index()
只会在索引不存在的时候建立一个索引。
下面的例子将使用test
数据库中的restaurants
集合。须要查看在集合中填充的实例数据,请参阅Import Example Dataset。
在Python命令行或者IDLE中,使用MongoClient链接一个正在运行的MongoDB实例,且已经打开test
数据库。
from pymongo import MongoClient client = MongoClient() db = client.test
在restaurants
集合中的cuisine
字段上建立自增的索引。
import pymongo db.restaurants.create_index([("cuisine", pymongo.ASCENDING)])
该方法将返回被建立的索引的名字。
"u'cuisine_1'"
MongoDB支持在多个字段上建立符合索引。这几个字段的命令将声明这个索引包含的键。举个例子,下面的操做将在cuisine
字段和address.zipcode
字段上建立一个复合索引。该索引将先对cuisine
的值输入一个升序的命令,而后对address.zipcode
的值输入一个降序命令。
import pymongo db.restaurants.create_index([ ("cuisine", pymongo.ASCENDING), ("address.zipcode", pymongo.DESCENDING) ])
该方法将返回被建立的索引的名字。
"u'cuisine_1_address.zipcode_-1'"