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 }