MongoDB 的简单使用(PyMongo驱动)

MongoDB

MongoDB 是由 C++ 编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似 JSON 对象,它的字段值可以包含其他文档、数组及文档数组,非常灵活。


连接 MongoDB

PyMongo 库安装:在命令提示符中输入 pip install pymongo

连接 MongoDB 时,可以使用 PyMongo 库里面的 MongoClient。一般来说,我们只需要向其传入 MongoDB 的 IP 及端口即可,其中第一个参数为地址 host,第二个参数为端口 port(默认 27017):

import pymongo

client = pymongo.MongoClient(host='localhost', port=27017)

这样就创建了 MongoDB 的连接对象。

另外,MongoClient 的第一个参数 host 还可以直接传入 MongoDB 的连接字符串:

client = pymongo.MongoClient('mongodb://localhost:27017/')

这可以达到同样的连接效果。


指定数据库

MongoDB 中可以建立多个数据库,下面指定操作其中一个数据库。这里以 test 数据库为例:

db = client.test

这里调用 client 的 test 属性即可返回 test 数据库。当然,我们也可以这样指定:

db = client['test']

这两种方式是等价的。


指定集合

MongoDB 的每个数据库又包含许多集合(collection),它们类似于关系型数据库中的表。

指定待操作的集合 students。与指定数据库类似,指定集合也有两种方式:

collection = db.students

或是

collection = db['students']

这样便声明了一个 Collection 对象。


插入数据

在 MongoDB 中,每条数据都有一个 _id 属性来唯一标识。

下面使用 insert_one 方法来插入单条记录:

# 此处对 students 集合新建一条数据,该数据以字典形式表示。
student = {
    'id': '20170101',
    'name': 'Jordan',
    'age': 20,
    'gender': 'male'
}

result = collection.insert_one(student) # insert_one 方法返回 InsertOneResult 对象
print(result)
print(result.inserted_id) # 调用 inserted_id 属性获取_id

运行结果如下:

<pymongo.results.InsertOneResult object at 0x10d68b558>
5932ab0f15c2606f0c1cf6c5

下面使用 insert_many 方法来插入多条记录,此处可以将数据以列表形式传递:

student1 = {
    'id': '20170101',
    'name': 'Jordan',
    'age': 20,
    'gender': 'male'
}

student2 = {
    'id': '20170202',
    'name': 'Mike',
    'age': 21,
    'gender': 'male'
}

result = collection.insert_many([student1, student2]) # insert_many 方法返回的类型是 InsertManyResult
print(result)
print(result.inserted_ids) # 调用 inserted_ids 属性获取插入数据的 _id 列表

运行结果如下:

<pymongo.results.InsertManyResult object at 0x101dea558>
[ObjectId('5932abf415c2607083d3b2ac'), ObjectId('5932abf415c2607083d3b2ad')]

查询

插入数据后,可以利用 find_one 或 find 方法进行查询,其中 find_one 查询得到的是单个结果,find 则返回一个生成器对象。

使用 find_one 方法查询:

result = collection.find_one({'name': 'Mike'})
print(type(result))
print(result)

此处查询 name 为 Mike 的数据,它的返回结果是字典类型,运行结果如下:

<class 'dict'>
{'_id': ObjectId('5932a80115c2606a59e8a049'), 'id': '20170202', 'name': 'Mike', 'age': 21, 'gender': 'male'}

可以发现,它多了 _id 属性,这是 MongoDB 在插入过程中自动添加的。

此外,我们也可以根据 ObjectId 来查询,此时需要调用 bson 库里面的 objectid:

from bson.objectid import ObjectId

result = collection.find_one({'_id': ObjectId('593278c115c2602667ec6bae')})
print(result)

其查询结果依然是字典类型,具体如下:

{'_id': ObjectId('593278c115c2602667ec6bae'), 'id': '20170101', 'name': 'Jordan', 'age': 20, 'gender': 'male'}

如果查询结果不存在,则会返回 None。

对于多条数据的查询,我们可以使用 find 方法:

results = collection.find({'age': 20})
print(results)
for result in results:
    print(result)

运行结果如下:

<pymongo.cursor.Cursor object at 0x1032d5128>
{'_id': ObjectId('593278c115c2602667ec6bae'), 'id': '20170101', 'name': 'Jordan', 'age': 20, 'gender': 'male'}
{'_id': ObjectId('593278c815c2602678bb2b8d'), 'id': '20170102', 'name': 'Kevin', 'age': 20, 'gender': 'male'}
{'_id': ObjectId('593278d815c260269d7645a8'), 'id': '20170103', 'name': 'Harden', 'age': 20, 'gender': 'male'}

返回结果是 Cursor 类型,它相当于一个生成器,遍历获取的所有结果,其中每个结果都是字典类型。

如果要查询年龄大于 20 的数据,则写法如下:

results = collection.find({'age': {'$gt': 20}})

此处查询的条件键值不是单纯的数字,而是一个字典,其键名为比较符号 $gt,意思是大于,键值为 20。

比较符号:

符号 含义 示例
$lt 小于 {‘age’: {’$lt’: 20}}
$gt 大于 {‘age’: {’$gt’: 20}}
$lte 小于或等于 {‘age’: {’$lte’: 20}}
$gte 大于或等于 {‘age’: {’$gte’: 20}}
$ne 不等于 {‘age’: {’$ne’: 20}}
$in 在范围内 {‘age’: {’$in’: [20, 23]}}
$nin 不在范围内 {‘age’: {’$nin’: [20, 23]}}

另外,还可以进行正则匹配查询:

此处查询名字以 M 开头的学生数据。

results = collection.find({'name': {'$regex': '^M.*'}})

此处使用 $regex 来指定正则匹配,^M.* 代表以 M 开头的正则表达式。

功能符号:

符号 含义 示例 示例含义
$regex 匹配正则表达式 {‘name’: {’$regex’: '^M.*}} name 以 M 开头
$exists 属性是否存在 {‘name’: {’$exists’: True}} name 属性存在
$type 类型判断 {‘age’: {’$type’: ‘int’} age 的类型为 int
$mod 数字模操作 {‘age’: {’$mod’: [5, 0]}} 年龄模 5 余 0
$text 文本查询 {’$text’: {‘search’: ‘Mike’}} text 类型的属性中包含 Mike 字符串
$where 高级条件查询 {’$where’: ‘obj.fans_ count== obj.follows_ count’} 自身粉丝数等于关注数

计数

要统计查询结果有多少条数据,可以调用 count 方法。

此处统计所有数据条数:

count = collection.find().count()
print(count)

此外还可以统计符合某个条件的数据:

count = collection.find({'age': 20}).count()
print(count)

运行结果是一个数值,即符合条件的数据条数。


排序

排序时可以直接调用 sort 方法,并在其中传入排序的字段及升降序标志。

示例:

results = collection.find().sort('name', pymongo.ASCENDING)
print([result['name'] for result in results])

运行结果如下:

['Harden', 'Jordan', 'Kevin', 'Mark', 'Mike']

此处调用 pymongo.ASCENDING 指定升序。

如果要降序排列,可以传入 pymongo.DESCENDING。


偏移

在某些情况下,可能只需要取某几个元素,这时可以利用 skip 方法偏移几个位置,比如偏移 2,就代表忽略前两个元素,得到第 3 个及以后的元素:

results = collection.find().sort('name', pymongo.ASCENDING).skip(2)
print([result['name'] for result in results])

运行结果如下:

['Kevin', 'Mark', 'Mike']

另外还可以用 limit 方法指定要取的结果个数:

results = collection.find().sort('name', pymongo.ASCENDING).skip(2).limit(2)
print([result['name'] for result in results])

运行结果如下:

['Kevin', 'Mark']

如果不使用 limit 方法,原本会返回 3 个结果,加了限制后,就会截取两个结果返回。

值得注意的是,在数据量非常庞大的时候,比如在查询千万、亿级别的数据库时,最好不要使用大的偏移量,因为这样很可能导致内存溢出。此时可以使用类似如下操作来查询:

from bson.objectid import ObjectId
collection.find({'_id': {'$gt': ObjectId('593278c815c2602678bb2b8d')}})

这就需要记录好上次查询的 _id。


更新

对于数据更新,可以使用 update_one 方法和 update_many 方法,它们的第 2 个参数需要使用 $ 类型操作符作为字典的键名。

首先指定查询条件,然后将数据查询出来,修改对应数据后调用 update 方法将原条件和修改后的数据传入:

condition = {'name': 'Kevin'}
student = collection.find_one(condition)
student['age'] = 26
result = collection.update_one(condition, {'$set': student})
print(result)
print(result.matched_count, result.modified_count)

上面调用了 update_one 方法,第 2 个参数不能直接传入修改后的字典,而是需要使用 {’$set’: student} 这样的形式,其返回结果是 UpdateResult 类型。然后分别调用 matched_count 和 modified_count 属性,可以获得匹配的数据条数和影响的数据条数。

使用 $set 操作符对数据进行更新可以只更新 student 字典内存在的字段。如果原先还有其他字段,则不会更新,也不会删除。

运行结果如下:

<pymongo.results.UpdateResult object at 0x10d17b678>
1 0

再看一个例子:

condition = {'age': {'$gt': 20}}
result = collection.update_one(condition, {'$inc': {'age': 1}})
print(result)
print(result.matched_count, result.modified_count)

这里指定查询条件为年龄大于 20,然后更新条件为 {’$inc’: {‘age’: 1}},表示年龄加 1,执行之后会将第一条符合条件的数据年龄加 1。

运行结果如下:

<pymongo.results.UpdateResult object at 0x10b8874c8>
1 1

可以看到匹配条数为 1 条,影响条数也为 1 条。

如果调用 update_many 方法,则会将所有符合条件的数据都更新:

condition = {'age': {'$gt': 20}}
result = collection.update_many(condition, {'$inc': {'age': 1}})
print(result)
print(result.matched_count, result.modified_count)

这时匹配条数就不再为 1 条了,运行结果如下:

<pymongo.results.UpdateResult object at 0x10c6384c8>
3 3

此时所有匹配到的数据都会被更新。


删除

删除操作可以调用 delete_one 和 delete_many 方法,并指定删除的条件,符合条件的所有数据均会被删除。

示例:

result = collection.delete_one({'name': 'Kevin'})
print(result)
print(result.deleted_count)
result = collection.delete_many({'age': {'$lt': 25}})
print(result.deleted_count)

运行结果如下:

<pymongo.results.DeleteResult object at 0x10e6ba4c8>
1
4

delete_one 即删除第一条符合条件的数据,delete_many 即删除所有符合条件的数据。它们的返回结果都是 DeleteResult 类型,可以调用 deleted_count 属性获取删除的数据条数。


其他操作

PyMongo 还提供了一些组合方法,如 find_one_and_delete、find_one_and_replace 和 find_one_and_update,它们分别用于查找后删除、替换和更新操作,其使用方法与上述方法基本一致。

另外还可以对索引进行操作,相关方法有 create_index、create_indexes 和 drop_index 等。

PyMongo 官方文档


Reference:https://kaiwu.lagou.com/course/courseInfo.htm?courseId=46#/detail/pc?id=1671

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章