1.pymongo入门教程
本文大体对pymongo3.9.0(当然也符合3.10.1)入门教程的翻译。并简要介绍mongodb。
1.1.MongoDB
MongoDB 是目前最流行的 NoSQL 数据库之一,使用的数据类型 BSON(类似 JSON)
1.1.1概念解析
不管我们学习什么数据库都应该学习其中的基础概念,在mongodb中基本的概念是文档、集合、数据库。 下面看一下与关系数据库的对比。
SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
database | database | 数据库 |
table | collection | 数据库表/集合 |
row | document | 数据记录行/文档 |
column | field | 数据字段/域 |
index | index | 索引 |
table joins | 表连接,MongoDB不支持 | |
primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
1.2.pymongo库
pymongo是python中于操作mongodb的一个库。且是从Python使用MongoDB的推荐方式 。
一下代码是紧接着的, 在同一个python shell中进行尝试。
1.2.1.Making a Connection with MongoClient
第一步使用pymongo是创建一个MongoClient
实例。
from pymongo import MongoClient
"""
①创建一个MongoClient的实例, 对应着mongo客户端
"""
#无参, 会连接到默认host和port
client = MongoClient()
#当然你也可以指定host和port
client2 = MongoClient('localhost', 27017)
#或者使用如下形式
client3 = MongoClient('mongodb://localhost:27017/')
1.2.2.获得数据库
单个MonDB实例支出多个独立的数据库。你可以使用属性风格获取数据库,格式如下:
实例.数据库名
db = client.test_database
对于包含特殊字符的数据库命名, 如test-database, 你可以使用字典风格获取
db2 = client['test-database']
1.2.3.获取集合
获取集合, 集合的获取方法和上面获取数据库的方式相同, 一种是属性的形式, 一种是字典的形式。你只需要对数据库实例进行操作即可。
collection1 = db.test_collection
collection2 = db['test-collection']
需要注意的是mongo的数据库和集合是惰性创建的, 上面的命令都没有真正创建数据库或集合
直到第一个文档被插入数据库或集合中, 这些数据库或集合才被创建。
1.2.4. 文档
MongoDB中的数据使用JSON样式的文档表示(和存储)。
在pymongo中我们使用字典的形式来表示文档, 例如一个博客文章的发表信息我们可以用如下表示
import datetime
post = {
'author':'Mike',
'text':'我的第一篇博客',
'tags':['mongdb', 'python'],
'date':datetime.datetime.utcnow()
}
注意到, 文件可能包含python的内置类型, 他会自动被转化形成BSON类型(BSON是文档在mongodb中的存储形式, 类似于JSON)。
1.2.5.插入一条文件
可以使用insert_one()方法, 插入一条文件到集合中。
#获取post数据库
posts = db.posts
#插入一条数据并获取出入数据的_id
post_id = posts.insert_one(post).inserted_id
print(post_id)
这个_id
对应的值在集合中必须是唯一的。insert_one() 方法返回一个InsertOneResult的实例(即插入一个结果的实例)。插入文档时,如果文档中还没有_id
,则MongoDB会自动添加一个特殊_id
键。
插入文档后,可以通过以下方式查看当前数据库中的所有集合
cnames = db.list_collections_names()
print(cnames)
1.2.6.使用find_one() 获取单个文档
find_one()返回与查询匹配的单个文档(如果不存在返回None)
import pprint
post1 = posts.find_one()
#使用pprint打印出来
pprint.pprint(post1)
find_one()方法 支持查询指定匹配的元素。如下查询作者为MIke的文档
post2 = posts.find_one({'author':'Mike'})
pprint.pprint(post2)
1.2.7.通过objectId查询
我们可以通过_id
进行查询
post3 = posts.find_one({'_id':post_id}) #注意这里的post_id 是bson.objectid.ObjectId的实例, 不是str类型的实例
print(post3)
通常在web应用中需获取的id一般是字符串, 我们可以将其转化为ObjectId对象, 再查询
from bson.objectid import ObjectId
def get(post_id):
# Convert from string to ObjectId:
document = client.db.collection.find_one({'_id': ObjectId(post_id)})
注意:MongoDB以BSON格式存储数据。BSON字符串采用UTF-8编码,因此PyMongo必须确保其存储的任何字符串仅包含有效的UTF-8数据。
1.2.8.批量插入
我们可以使用insert_many()方法插入多个文档。 只要将要插入的文档放入一个列表中
new_posts=[
{'author':'Mike',
'text':'我的第三篇文章',
"tags": ["bulk", "insert"],
'date':datetime.datetime.utcnow()
},
{'author': 'Mike',
'text': '我的第四篇文章',
"title":"我的第四篇文章",
'date': datetime.datetime.utcnow()
}
]
result = posts.insert_many(new_posts)
print(result.inserted_ids)
该方法返回一个pymongo.results.InsertManyResult类型。并且我们可以看到插入额度文档格式是不一样的, 如new_posts[1]中没有tags这个键值对, 而多了title这个键值对。
这说明MongoDB是无模式的。这就是NoSQL数据库的特性。 我们都知道模式是型的概念, 对于关系数据库而言, 每个表都时有严格的模式。
1.2.9.查询读个文档
为了获得多个文档作为查询结果, 我们可以使用find()放回一个Cursor实例, 该实例使我们可以迭代所有匹配的文档。
cursor = posts.find()
for post in cursor:
pprint.pprint(post)
当然也可以像find_one()方法一样, 传入一个文档(即python中的字典)作为过滤器去限制返回结果。
for post in post.find({'author':'Mike'}):
pprint.pprint(post)
1.2.10.计数
如果我们只想知道集合中符合该匹配的文档有多少个, 可以使用count_documents()方法
posts.count_documents({})
posts.count_documents({'author':'Tao'})
1.2.11.范围查询
MongoDB支持很多高级查询。例如, 我们查询集合中早于某一时间的文档, 并且结果以作者排序。
d = datetime.datetime(2020,7,23,12)
for post in posts.find({'date':{'$lt':d}}).sort('author'):
pprint.pprint(post)
$lt
是运算符
1.2.12.索引
增加索有助于加快特定的查询, 并且可以为查询和存储添加额外功能。下面这个例子,我们将演示如何在一个key上创建唯一索引。
import pymongo
#创建一个集合
profiles = db['profiles']
result = profiles.create_index([('user_id', pymongo.ASCENDING)], unique=True)
#获取该集合的所有索引列表并打印
#profiles.index_information()返回一个包含索引信息的字典
print(sorted(list(profiles.index_information())))
你会看到列表中有两个索引, 一个_id
是Mongdb自动创建的索引, 里一个是我们刚刚创建的。如果插入含有相同索引的文档,就会mongodb拒绝插入。演示如下
user_profiles = [
{'user_id':216,'name':'Luks'},
{'user_id': 214, 'name': 'Taos'}
]
result = db.profiles.insert_many(user_profiles)
profiles.insert_one(
{'user_id':216,'name':'Tom'}
)
#pymongo.errors.DuplicateKeyError: E11000 duplicate key error collection: test.profiles index: user_id_1 dup key: { user_id: 216 }