python -- PyMongo

来源:互联网 发布:工业企业数据库 161 编辑:程序博客网 时间:2024/04/30 14:05

概述

PyMongo 是Python的发行版本,它包含一些工具,强烈推荐用于协同MongoDB进行工作。这个文档将会介绍一些使用PyMongo时需要知道的内容。

安装/更新
介绍如何获取发行版本

教程
快速介绍

案例
介绍如何完成指定任务

常见的问题
解答一些常常遇到的问题

Python3 的疑问
关于支持Python3被经常提及的问题

API文档
完整的API文档,被模块化的组织

工具
列举一些为MongoDB写的Python工具和库

如果你有一些关于Pyongo的问题,最好去 MongoDB 用户组提问,如果你得到答案,然后回来使用此文档或做点贡献,这会非常好。

关于MongoDB的所有问题,可以在“Python Driver”工程的MongDB JIRA bug tracker上报告。

PyMongo有许多的社区和贡献者在维护,可以对此文档做一些轻微的修改,或者在github上创建一个分支,并发送pull请求。

关于PyMongo的所有改变请查看 Changelog。所有老版本的文档,请查阅 archive list.

pymongo安装

安装pymongo [可以去python.org下载对应安装包]

git clone git://github.com/mongodb/mongo-python-driver.git pymongocd pymongo/python setup.py install

教程


该教程介绍MongoDB与Pymongo是如何协同工作的。

先决条件

在我们开始前,请确认PyMongo已经安装,在Python shell中,输入下面的命令如果没有出现异常,说明安装成功。
>>> import pymongo

如果未特别说明,教程中的MongoDB实例使用的都是默认的主机和端口。请确认你已经下载并安装MongoDB,你可以执行下面命令打开启用数据库
$ mongod


使用MongoClient创建一个连接

第一步就是针对mongdb创建一个实例。
>>> from pymongo import MongoClient
>>> client = MongoClient()

上述代码使用的是默认主机和端口,我们也可以按照下面方式指定。
>>> client = MongoClient('localhost', 27107)

或者MongoDB的URI格式
>>> client = MongoClient('mongodb://localhost:27107/')


获取数据库

一个MongoDB实例可以支持多个独立的数据库,使用MongoClient实例的属性方法,你可以访问对应的数据库。
>>> db = client.test_database

如果属性这种类型的访问方式不能工作,你可以使用字典形式的方法访问:
>>> db = client['test-database']


获取集合

集合表示存储在MongoDB中的档案,可以理解为数据库中的表。获取集合的方式与数据库类似:
>>> collection = db.test_collection


>>> collection = db['test-collection']

注意: MongDB的集合创建有个惰性的过程,上述的命令未对MongDB服务器完成任何操作。当有一条档案插入时,集合和数据库被创建。


档案

MongoDB的数据是以JSON形式表示和存储。在Pymongo中,用字典表示。

>>> import datetime
>>> post = {"author": "Mike",
            "text": "My first blog post!",
            "tags": ["mongodb", "python", "pymongo"],
            "date": datetime.datetime.utcnow()
}

档案可以包含原生的Python类型,这些类型可由BSON类型转换而来,或者转换过去。


插入档案

使用insert()方法,插入档案到集合中。
>>> posts = db.posts
>>> post_id = posts.insert(post)
>>> post_id
ObjectId('...')

插入指定建值时,如果"_id"未指定,mongoDB会自动添加"_id"。"_id"值在集合中必须唯一,insert()会返回插入档案的"_id"值。如果想要了解更多的信息,请查阅文档 on_id.

插入文档后,posts 集合被创建。我们可以列举数据库集合以确认。
>>> db.collection_names()
[u'system.indexes', u'posts']

注意: system.indexes 是一个特殊的内建集合,它会自动被创建。


使用find_one获取一条档案

MongoDB所做的大部分基本查询会用到 find_one(). 该方法会返回一条匹配的档案(如果没有匹配想,则返回None)。如果你只想知道是否存在匹配像,或着匹配的第一项,此方法会很有用。下面演示利用 find_one() 获取posts集合中的第一条档案。
>>> posts.find_one()
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}

结果返回了刚才插入的那条数据。
注: 返回的档案中包含一个"_id", 添加时自动生成。

find_one() 也支持查询元素,例如查询author为Mike的项。
>>> posts.find_one({"author": "Mike"})
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}


根据ObjectId进行查询

>>> post_id
ObjectId(...)
>>> posts.find_one({"_id": post_id})
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}

注意: ObjectId 与其对应的字符串不同。

>>> post_id_as_str = str(post_id)
>>> posts.find_one({"_id": post_id_as_str}) # No result
>>>

在find_one前,将字符串转为一个ObjectId对象是很必要的。
from bson.objectid import ObjectId

# The web framework gets post_id from the URL and passes it as a string
def get(post_id):
    # Convert from string to ObjectId:
    document = client.db.collection.find_one({'_id': ObjectId(post_id)})


留意Unicode字符串

你可能已经注意到了,我们前面存储的字符串,不同于服务器返回的字符串(例如. 返回 u'Mike' 而不是'Mike').

MongoDB的数据是以 BSON 格式存储。BSON将字符进行UTF-8编码,以便PyMongo确保任何字符串以UTF-8存储。常规的字符串(<type 'str'>)会被验证,并以原来的方式存储。 Unicode字符串(<type 'unicode'>)会被先编码为UTF-8.例子中显示的字符串是u'Mike',而不是'Mike',主要是因为PyMongo将BSON字符串解码为unicode字符串,而不是常规字符。


批量插入

为了让查询变的更有意思,我们插入多条档案。传入迭代器参数到 insert(),可以实现批量插入。

>>> new_posts = [{"author": "Mike",
                  "text": "Another post!",
                  "tags": ["bulk", "insert"],
                  "date": datetime.datetime(2009, 11, 12, 11, 14)},
                 {"author": "Eliot",
                  "title": "MongoDB is fun",
                  "text": "and pretty easy too!",
                  "date": datetime.datetime(2009, 11, 10, 10, 45)}]
>>> posts.insert(new_posts)
[ObjectId('...'), ObjectId('...')]

下面有两件事需要注意:
insert() 返回了两个ObjectId实例,一个代表一个档案。
new_posts[1] 与其他posts比,有一个不同的"形态" - 它没有"tags"域,多了一个"title"域。这就是我们常说的MongoDB的自由模式。


查询多条档案

使用 find() 方法,会返回一个 Cursor 使用,它允许我们迭代返回所有匹配项。例如:
>>> for post in posts.find():
...   post
...
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']}
{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'}

就像我们使用find_one()那样, find用法如下:
>>> for post in posts.find({"author": "Mike"}):
...   post
...
{u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'mongodb', u'python', u'pymongo']}
{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']}


统计

如果我们想知道匹配项的数目,可以执行count()操作,不用做完整的查询。我们可以获取集合中所有档案的数目。
>>> posts.count()
3
>>> posts.find({"author":"Mike"}).count()
2


范围查询

MongoDB支持许多不同类型的高级查询。
>>> d = datetime.datetime(2009, 11, 12, 12)
>>> for post in posts.find({"date": {"$lt":d}}).sort("author"):
        print post
{u'date': datetime.datetime(2009, 11, 10, 10, 45), u'text': u'and pretty easy too!', u'_id': ObjectId('...'), u'author': u'Eliot', u'title': u'MongoDB is fun'}
{u'date': datetime.datetime(2009, 11, 12, 11, 14), u'text': u'Another post!', u'_id': ObjectId('...'), u'author': u'Mike', u'tags': [u'bulk', u'insert']}


索引

为了让查询速度更快,我们可以添加一个"date"和"author"的复合索引。
>>> posts.find({"date": {"$lt": d}}).sort("author").explain()["cursor"]
u'BasicCursor'
>>> posts.find({"date": {"$lt": d}}).sort("author").explain()["nscanned"]
3

上面的结果显示,查询用到了BasicCursor,并扫描了3个档案。接下来我们创建一个复合索引,然后看看同样的信息:
>>> from pymongo import ASCENDING, DESCENDING
>>> posts.create_index([("date", DESCENDING), ("author", ASCENDING)])
u'date_-1_author_1'
>>> posts.find({"date": {"$lt": d}}).sort("author").explain()["cursor"]
u'BtreeCursor date_-1_author_1'
>>> posts.find({"date":{"$lt":d}}).sort("author").explain()["nscanned"]
2

0 0
原创粉丝点击