四时宝库

程序员的知识宝库

Python使用MongoDB完全指南(python的mongodb)

我们在上一文中,介绍了关系型数据库的相关使用,本文接着来介绍另一重要的数据库类型,非关系型数据库NoSQL)。NoSQL 是基于键值对的存储方式,不需要经过 SQL 层的解析,数据之间也没有耦合性,因此其性能非常高。常见的非关系型数据库有 MongoDBNeo4JHBaseRedis 等,本文使用常用的 MongoDB 来讲解非关系型数据库的使用。

MongoDB 是由 C++编写而成,是一个基于分布式文件存储的开源数据库系统,其存储形式类似于 json 对象,因此在使用时非常灵活,被广泛使用。

初始工作

Python 使用 MongoDB 数据库需要第三方库来支持,因此需要先安装 pymongo 库。

pip install pymongo

快速上手

import pymongo
# 建立连接
client = pymongo.MongoClient(host="localhost", port=27017)

# 引用数据库名称,这里假设要创建名为mydatabase的数据库
db = client['mydatabase']

# 要验证数据库是否已存在,可以列出所有数据库名称
print(client.list_database_names())

# 若要进一步操作,比如创建集合并插入数据
collection_name = 'mycollection'
data = {'name': 'example document'}
# 新增数据
db[collection_name].insert_one(data)

开始使用

非关系型数据库关系型数据库在概念上存在一定差异,如下表:

指定使用的数据库(database)

一般在应用中会存在多个数据库,并且在操作数据的时候需要指定是哪个具体的数据库,如下:

# 下方client为建立连接后的client对象

# 使用属性的方式
db = client['mydatabase']
# 使用点模式
db = client.mydatabase

这里我们选择了“mydatabase”这个数据库,需要注意的是,如果这个数据库不存在,后续在执行数据插入的时候会自动创建该库(非常给力的一个功能)

指定集合

在 MongoDB 的一个数据库中,可以包含多个 collection(集合, 可以类比为 MySQL 中的表),因此在操作数据的时候还需要指定集合。我们只需要使用上边获取的数据并使用属性就可以获取到指定集合。

# 下边db指获取到的库
# 属性获取
collection = db['mycollection']
# 点模式获取
collection = db.mycollection

新增数据

在获取到数据后就可以使用 insert* 方法来新增数据了。

collection.insert_one(
    {'name': 'example document', 
     'age': 18, 
     'address': 'beijing', 
     'phone': '1234567890'})

如上图所示使用 insert_one 方法新增一条数据。

还可以使用 insert_many 来同时新增多条数据

collection.insert_many(
    [{'name': 'example1', 'age': 18, 'address': 'beijing'}
      ,{'name': 'example2', 'age': 18, 'address': 'beijing'}])

从上边运行结果可以看出, MongoDB 在新增数据时,只需要新增即可,数据库会自动设置一个 _id 属性来表示主键。此 _id 值由 MongoDB 来维护。并且新增成功后,方法会返回一个InsertOneResult 对象,其中包含了数据 _id 值,需要注意的是,这里的_id是ObjectId对象。

数据查询

数据存入后,最重要的就是要根据合适的条件取出来,此时可以使用 find*方法来获取已经存入的数据,当然,pymongo 中提供了更多的方法来支持这些功能,如下。

find_one 查找一条结果

# 获取一条数据,其中name为"example document"
res = collection.find_one({"name": "example document"})
print(res)
# {'_id': ObjectId('65a8c06271f39c34e5e98579'), 'name': 'example document'}
print(type(res))
# <class 'dict'>

如上述代码中,我们使用 find_one 查找一条 name "example document"的内容,并返回一个 dict,如果没有匹配的条件则返回 None

需要特别注意的是,如果使用数据主键 _id 查询,需要使用 ObjectId 构建 id 值,直接使用字符串查找会无法查询到结果。

# 需要使用ObjectId构建id
res = collection.find_one({"_id": ObjectId("65a8c06271f39c34e5e98579")})

find 查找多条

res = collection.find({'name': 'example document'})

print(res)

for row in res:
    print(row)

# <pymongo.cursor.Cursor object at 0x000001DCE4578E90>
# {'_id': ObjectId('65a8c06271f39c34e5e98579'), 'name': 'example document'}
# {'_id': ObjectId('65a8c098a6c8916e18ee8e80'), 'name': 'example document'}

使用 find 方法将会查找出所有符合条件的数据,并封装到了 Cursor 对象中,因此需要遍历当前对象才可以获取到每条数据。MongoDB提供了非常丰富的条件查询,以下是一些常用示例:

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

如上代码中, 查找 age 大于 20 的数据,需要注意的是,条件是一个对象的结构

其他操作

计数

早先的版本中可以使用 find 返回的结果使用 count 方法来计数, 但是这个方法在后续版本中被废弃了, 现在需要使用 count_documents 来统计条件下的查询的数量。

count = collection.count_documents({})
print("count:", count) #10

排序

与关系型数据库相似的, MongoDB 也支持排序,find 结果后调用 sort,并指定排序方式即可完成结果排序

# ASCENDING = 1
# """Ascending sort order."""
# DESCENDING = -1
# """Descending sort order."""

res = collection.find()
rows = res.sort("name", pymongo.ASCENDING)

排序参数可以使用pymongo 中定义的常量,也可以直接赋值 1 或-1

偏移

熟悉后台开发的一定使用过分页, 在 MongoDB 中也支持这样的操作, 但是需要搭配 skip 和 limit 两个方法来完成

res = collection.find()
row = res.skip(2).limit(2)

如上所示,使用 skip 跳过前两条, 使用 limit 方法获取结果中的 2 条数据, 结果中最终会返回第 3,4 条数据。不过需要注意的是,这样的查找在数据量较大的情况下需要慎用,可能会导致内存不足,一般的解决方式是记录上一次查询最后一条数据的 id,然后查找此大于此 id 值的,再进行 limit 限制

更新数据

更新数据时,需要使用 update 方法来完成。

collection.update_one({'name': 'example document'}, 
                      {"$set": {"name": "测试数据", "age": 30}})

如上述代码中,update_one 接受两个参数, 第一个参数为查询条件, 第二个参数为需要设置的内容。

在上方数据查询中有find_one_and_update 方法也可以在完成更新的操作

clt.find_one_and_update({'name': 'example document'}, 
                        {"$set": {"name": "测试数据2", "age": 30}})

两者执行本质是一样的,都是先查询,后更新

删除数据

删除数据时,需要使用 delete_one 方法来完成,返回DeleteResult 结果中包含了操作成功的条数,如果操作不成功则返回 None

res = clt.delete_one({'name': 'example1'})

# DeleteResult({'n': 1, 'ok': 1.0}, acknowledged=True)

在上方数据查询中有find_one_and_delete 方法也可以完成删除操作, 不过该方法不返回任何结果

clt.find_one_and_delete({'name': 'example2'})

#我来唠家常#

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接