ZetCode

PyMongo

最后修改于 2024 年 1 月 29 日

PyMongo 教程展示了如何在 Python 中编写 MongoDB 程序。代码示例可在作者的 Github 仓库 中找到。

MongoDB 是一个 NoSQL 跨平台面向文档的数据库。它是目前最流行的数据库之一。MongoDB 由 MongoDB Inc. 开发,并作为免费和开源软件发布。

MongoDB 中的一个记录是文档,它是由字段和值对组成的数据结构。MongoDB 文档类似于 JSON 对象。字段的值可能包含其他文档、数组以及文档数组。MongoDB 将文档存储在集合中。集合类似于关系数据库中的表,文档类似于行。

一个游标是对查询结果集的引用。客户端可以遍历游标以检索结果。默认情况下,游标在不活动十分钟后超时。

PyMongo

PyMongo 是一个用于在 Python 中使用 MongoDB 的 Python 模块。

安装 PyMongo

以下命令用于安装 PyMongo。

$ sudo pip install pymongo

我们使用 pip 安装 PyMongo。

创建 MongoDB 数据库

mongo 工具是一个与 MongoDB 交互的 JavaScript shell 界面,它为系统管理员提供了一个接口,也为开发人员提供了一种直接与数据库测试查询和操作的方式。

$ mongo testdb
MongoDB shell version: 2.6.10
connecting to: testdb
> show dbs
admin   (empty)
local   0.078GB
test    0.078GB
testdb  0.078GB

我们创建一个 testdb 数据库。

PyMongo 创建集合

在第一个示例中,我们创建了一个新的集合。MongoDB 将文档存储在集合中。集合类似于关系数据库中的表。

create_collection.py
#!/usr/bin/python

from pymongo import MongoClient

cars = [ {'name': 'Audi', 'price': 52642},
    {'name': 'Mercedes', 'price': 57127},
    {'name': 'Skoda', 'price': 9000},
    {'name': 'Volvo', 'price': 29000},
    {'name': 'Bentley', 'price': 350000},
    {'name': 'Citroen', 'price': 21000},
    {'name': 'Hummer', 'price': 41400},
    {'name': 'Volkswagen', 'price': 21600} ]

client = MongoClient('mongodb://:27017/')

with client:

    db = client.testdb
    
    db.cars.insert_many(cars)

该示例创建了一个新的 cars 集合。它包含八个文档。

cars = [ {'name': 'Audi', 'price': 52642},
    {'name': 'Mercedes', 'price': 57127},
    {'name': 'Skoda', 'price': 9000},
    {'name': 'Volvo', 'price': 29000},
    {'name': 'Bentley', 'price': 350000},
    {'name': 'Citroen', 'price': 21000},
    {'name': 'Hummer', 'price': 41400},
    {'name': 'Volkswagen', 'price': 21600} ]

此 Python 字典存储了要插入 MongoDB 集合的八条记录。

client = MongoClient('mongodb://:27017/')

MongoClient 用于与 MongoDB 通信。我们将主机名和端口号传递给 MongoClient

db = client.testdb

我们获取对 testdb 数据库的引用。

db.cars.insert_many(cars)

使用 insert_many 方法,我们将八个文档插入到 cars 集合中,该集合也会被自动创建。

> db.cars.find()
{ "_id" : ObjectId("5b41eb21b9c5d915989d48a8"), "price" : 52642, "name" : "Audi" }
{ "_id" : ObjectId("5b41eb21b9c5d915989d48a9"), "price" : 57127, "name" : "Mercedes" }
{ "_id" : ObjectId("5b41eb21b9c5d915989d48aa"), "price" : 9000, "name" : "Skoda" }
{ "_id" : ObjectId("5b41eb21b9c5d915989d48ab"), "price" : 29000, "name" : "Volvo" }
{ "_id" : ObjectId("5b41eb21b9c5d915989d48ac"), "price" : 350000, "name" : "Bentley" }
{ "_id" : ObjectId("5b41eb21b9c5d915989d48ad"), "price" : 21000, "name" : "Citroen" }
{ "_id" : ObjectId("5b41eb21b9c5d915989d48ae"), "price" : 41400, "name" : "Hummer" }
{ "_id" : ObjectId("5b41eb21b9c5d915989d48af"), "price" : 21600, "name" : "Volkswagen" }

我们使用 mongo 工具验证数据。

PyMongo 列出集合

使用 collection_names,我们可以获取数据库中可用集合的列表。

list_collections.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb
    print(db.collection_names())

该示例打印 testdb 数据库中的集合。

PyMongo 删除集合

drop 方法从数据库中删除一个集合。

drop_collection.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:

    db = client.testdb

    db.cars.drop()

该示例从 testdb 数据库中删除 cars 集合。

PyMongo 运行命令

我们可以使用 command 向 MongoDB 发出命令。serverStatus 命令返回 MongoDB 服务器的状态。

server_status.py
#!/usr/bin/python

from pymongo import MongoClient
from pprint import pprint

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb

    status = db.command("serverStatus")
    pprint(status)

该示例打印详细的服务器状态。

dbstats 命令返回反映单个数据库使用状态的统计信息。

db_stats.py
#!/usr/bin/python

from pymongo import MongoClient
from pprint import pprint

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb
    print(db.collection_names())

    status = db.command("dbstats")
    pprint(status)

该示例打印 testdb 的数据库统计信息。

PyMongo 游标

find 方法返回一个 PyMongo 游标,它是查询结果集的引用。

cursor.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb

    cars = db.cars.find()

    print(cars.next())
    print(cars.next())
    print(cars.next())
    
    cars.rewind()

    print(cars.next())
    print(cars.next())
    print(cars.next())    

    print(list(cars))

在示例中,我们处理一个游标。

cars = db.cars.find()

find 方法返回一个 PyMongo 游标。

print(cars.next())

使用 next 方法,我们从结果集中获取下一个文档。

cars.rewind()

rewind 方法将游标重置到其未评估状态。

print(list(cars))

使用 list 方法,我们可以将游标转换为 Python 列表。它会将所有数据加载到内存中。

PyMongo 读取所有数据

在下面的示例中,我们读取集合中的所有记录。我们使用 Python for 循环遍历返回的游标。

all_cars.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:

    db = client.testdb

    cars = db.cars.find()

    for car in cars:
        print('{0} {1}'.format(car['name'], 
            car['price']))

该示例打印集合中所有汽车的名称及其价格。

cars = db.cars.find()

find 方法在集合或视图中选择文档,并返回指向所选文档的游标。游标是查询结果集的引用。

for car in cars:
    print('{0} {1}'.format(car['name'], 
        car['price']))

使用 Python for 循环,我们遍历结果集。

$ ./all_cars.py 
Audi 52642
Mercedes 57127
Skoda 9000
Volvo 29000
Bentley 350000
Citroen 21000
Hummer 41400
Volkswagen 21600

PyMongo 计算文档数

文档数量使用 count 方法检索。

count_cars.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:

    db = client.testdb

    n_cars = db.cars.find().count()

    print("There are {} cars".format(n_cars))

该示例使用 count 计算集合中汽车的数量。

$ ./count_cars.py 
There are 8 cars

集合中有八辆车。

PyMongo 过滤器

findfind_one 的第一个参数是过滤器。过滤器是所有文档必须匹配的条件。

filtering.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb

    expensive_cars = db.cars.find({'price': {'$gt': 50000}})

    for ecar in expensive_cars:
        print(ecar['name'])

该示例打印价格大于 50000 的汽车名称。

expensive_cars = db.cars.find({'price': {'$gt': 50000}})

find 方法的第一个参数是所有返回记录必须匹配的过滤器。该过滤器使用 $gt 操作符仅返回昂贵的汽车。

$ ./filtering.py 
Audi
Mercedes
Bentley

PyMongo 投影

使用投影,我们可以从返回的文档中选择特定字段。投影作为 find 方法的第二个参数传递。

projection.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb

    cars = db.cars.find({}, {'_id': 1, 'name':1})

    for car in cars:
        print(car)

该示例打印文档的 _idname 字段。

cars = db.cars.find({}, {'_id': 1, 'name':1})

我们可以指定包含或排除投影,但不能同时两者都指定。

$ ./projection.py 
{'name': 'Audi', '_id': ObjectId('5b41eb21b9c5d915989d48a8')}
{'name': 'Mercedes', '_id': ObjectId('5b41eb21b9c5d915989d48a9')}
{'name': 'Skoda', '_id': ObjectId('5b41eb21b9c5d915989d48aa')}
{'name': 'Volvo', '_id': ObjectId('5b41eb21b9c5d915989d48ab')}
{'name': 'Bentley', '_id': ObjectId('5b41eb21b9c5d915989d48ac')}
{'name': 'Citroen', '_id': ObjectId('5b41eb21b9c5d915989d48ad')}
{'name': 'Hummer', '_id': ObjectId('5b41eb21b9c5d915989d48ae')}
{'name': 'Volkswagen', '_id': ObjectId('5b41eb21b9c5d915989d48af')}

PyMongo 排序文档

我们可以使用 sort 对文档进行排序。

sorting.py
#!/usr/bin/python

from pymongo import MongoClient, DESCENDING

client = MongoClient('mongodb://:27017/')

with client:

    db = client.testdb

    cars = db.cars.find().sort("price", DESCENDING)

    for car in cars:
        print('{0} {1}'.format(car['name'], 
            car['price']))

该示例按价格降序排序记录。

$ ./sorting.py 
Bentley 350000
Mercedes 57127
Audi 52642
Hummer 41400
Volvo 29000
Volkswagen 21600
Citroen 21000
Skoda 9000

PyMongo 聚合

聚合计算集合中数据的聚合值。

aggregate_sum.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb

    agr = [ {'$group': {'_id': 1, 'all': { '$sum': '$price' } } } ]

    val = list(db.cars.aggregate(agr))

    print('The sum of prices is {}'.format(val[0]['all']))

该示例计算所有汽车价格的总和。

agr = [ {'$group': {'_id': 1, 'all': { '$sum': '$price' } } } ]

$sum 运算符计算并返回数值的总和。$group 运算符根据指定的标识符表达式对输入文档进行分组,并对每个组应用指定的累加器表达式。$sum 运算符用于计数。

val = list(db.cars.aggregate(agr))

aggregate 方法将聚合操作应用于 cars 集合。

$ ./aggregate_sum.py 
The sum of prices is 581769

所有值的总和为 581769。

我们可以使用 $match 运算符来选择要聚合的特定汽车。

sum_two_cars.py
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb

    agr = [{ '$match': {'$or': [ { 'name': "Audi" }, { 'name': "Volvo" }] }}, 
        { '$group': {'_id': 1, 'sum2cars': { '$sum': "$price" } }}]

    val = list(db.cars.aggregate(agr))

    print('The sum of prices of two cars is {}'.format(val[0]['sum2cars']))

该示例计算奥迪和沃尔沃汽车价格的总和。

agr = [{ '$match': {'$or': [ { 'name': "Audi" }, { 'name': "Volvo" }] }}, 
    { '$group': {'_id': 1, 'sum2cars': { '$sum': "$price" } }}]

该表达式使用 $match$or$group$sum 运算符来完成任务。

$ ./sum_two_cars.py 
The sum of prices of two cars is 81642

两辆车的价格总和为 81642。

PyMongo 限制数据输出

limit 查询选项指定要返回的文档数量,而 skip 选项跳过一些文档。

MongoSkipLimit.java
#!/usr/bin/python

from pymongo import MongoClient

client = MongoClient('mongodb://:27017/')

with client:
    
    db = client.testdb

    cars = db.cars.find().skip(2).limit(3)

    for car in cars:
        print('{0}: {1}'.format(car['name'], car['price']))

该示例从 cars 集合读取,跳过前两个文档,并将输出限制为三个文档。

cars = db.cars.find().skip(2).limit(3)

skip 方法跳过前两个文档,limit 方法将输出限制为三个文档。

$ ./limit_documents.py 
Skoda: 9000
Volvo: 29000
Bentley: 350000

来源

Python PyMongo 文档

在 PyMongo 教程中,我们已经使用 MongoDB 和 Python 进行开发。

作者

我叫 Jan Bodnar,是一名充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Python 教程