美文网首页我爱编程
Python-MongoDB翻译

Python-MongoDB翻译

作者: 点点寒彬 | 来源:发表于2016-03-14 20:34 被阅读216次

    文章首发:点点寒彬的博客

    前言

    都说MongoDB这个NoSql数据库特别友好,使用起来也非常方便,今天稍微接触了一下,发现真的是非常非常简单,但是网上对这块内容涉及的很少,而且很多内容都是很老的版本使用的方法,我看了一下官方API文档中描述的内容也不多,顺手翻译一下吧,造福一下后来人。

    注:我并不是逐字逐句的翻译,在某些地方我无法精确翻译的时候,我概括了大概的意思,有能力的可以直接看官方文档

    前提条件

    首先,我们需要安装PyMongo模块,在PythonShell中下面的代码能正常运行且无报错。

    >>> import pymongo
    

    当然,你的MongoDB需要在默认地址和端口开启,你可以按照这个方法确认你是否安装了MongoDB:

    $ mongod
    

    建立一个MongoClient

    第一步我们需要建立一个MongoClient来运行MongoDB,这个做起来非常简单:

    >>> from pymongo import MongoClient
    >>> client = MongoClient()
    

    上面的代码会连接默认的地址和端口,我们也可以自己指定地址和端口,像下面这样:

    >>> client = MongoClient('localhost', 27017)
    

    或者使用MongoDB的URI连接:

    >>> client = MongoClient('mongodb://localhost:27017/')
    

    获取数据库

    一个MongoDB可以提供多个数据库接口。当使用PyMongo的时候,你可以使用获取属性的方式建立MongoClient:

    >>> db = client.test_database
    

    如果你使用上面的方法无法获取数据库的时候,你可以使用字典的方式来获取数据库。

    获取连接

    获取连接的方式和获取数据库的方式一样,也可以使用获取属性的方式:

    >>> collection = db.test_collection
    

    或者使用字典的方式:

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

    注意:使用MongoDB建立连接非常容易,但是上面的所有操作都不是实实在在的操作了MongoDB,当第一次获取数据库和建立连接的时候,数据库和连接会被创建。

    文档

    MongoDB的数据格式存储使用的是JSON风格,在PyMongo中,我们使用的字典类型就相当于数据。比如下面的数据就类似博客中的post信息:

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

    数据格式可以容纳python的类型(就像datetime.datetime)

    插入数据

    往数据库插入一条数据我们使用insert_one()方法:

    >>> posts = db.posts
    >>> post_id = posts.insert_one(post).inserted_id
    >>> post_id
    ObjectId('...')
    

    当我们插入数据成功的时候,MongoDB会生成一个特殊的主键“_id”。这个主键“_id”的值是唯一的。insert_one()返回的值就是这个主键的值。

    插入第一条数据后,数据库、数据表和连接都建立了,我们可以查看列表中的所有信息:

    >>> db.collection_names(include_system_collections=False)
    [u'posts']
    

    使用find_one()方法获取一条记录

    在MongoDB中最基本的方法就是find_one()。这个方法返回一条符合条件的记录(或者None)。当你知道某条信息只有一个的时候,这个方法非常有用,或者返回第一条数据,这里我们使用这个方法获取第一条数据:

    >>> posts.find_one()
    {u'date': datetime.datetime(...), u'text': u'My first blog post!', u'_id': ObjectId('...'), u'author': u'Mike'
    

    结果是我们之前插入的一条字典型的数据。

    注意:返回结果中的“_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'
    

    如果我们把author换成另外一个,则不会返回结果:

    >>> posts.find_one({"author": "Eliot"})
    >>>
    

    使用ObjectId查询

    我们也可以用“_id”来查询,下面是我们的示例:

    >>> 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'
    

    注意:ObjectId和转换为字符串的ObjectId是不一样的:

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

    在web应用中一个很常见的现象就是从URI中获取ObjectId来查询后台记录。在使用这个之前需要把str类型转换成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 Strings注意事项

    你可能会注意到我们的数据和存进去的数据有一些不一样,比如( u’Mike’ 而不是‘Mike’)。

    MongoDB是使用BSON来存储数据。BSON是使用utf-8来编码的。所以PyMongo存储的str类型必须是utf-8的。(‘str’类型)也是要被支持的,因此Unicode类型(<‘unicode’类型>)需要先编码成utf-8,我们的示例中PythonShell显示的是u’Mike’而不是‘Mike’就是因为PyMongo解码了BSON的string变成Python的unicode string。

    大量的插入数据

    为了让查询更有意思,我们需要插入多一些数据。能够新增一条记录,我们也可以做到新增多条记录。使用insert_many()方法插入由第一条数据组成的列表,只需要往服务端发送一条命令:

    >>> 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)}]
    >>> result = posts.insert_many(new_posts)
    >>> result.inserted_ids
    [ObjectId('...'), ObjectId('...')]
    

    这个例子有几个有意思的地方:

    • insert_many()返回了两个相互对应ObjectId
    • new_post[1]有一个不同的地方,多了一个“tags”字段。而现在我们又多了一个字段,这就是我们说MongoDB非常schema-free(开放?)

    查询一条以上的记录

    我们使用find()方法来获取一条以上的记录。find()返回一组符合条件的记录,并且允许我们通过迭代的方式获取它们。例如,在post中我们可以迭代的获取所有查询的数据:

    >>> 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()一样,我们也可以在这里加上查询条件来获取符合条件的数据:

    >>> 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还提供了许多种类的查询方式。例如我们查询数据的日期小于某一个日期,且按照author字段来排序:

    >>> 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']}
    

    这里我们使用“$lt”来做一个限制的查询,使用sort()来对author字段排序。

    主键

    增加一个主键能够帮助我们快速而准确的查询记录,也可以使我们存储的数据更加有用。在这个示例中,我们将会展示在一个已存在主键的表中新增一个主键:

    首先,我们要新增一个主键:

    >>> result = db.profiles.create_index([('user_id', pymongo.ASCENDING)],
    ...                                   unique=True)
    >>> list(db.profiles.index_information())
    [u'user_id_1', u'_id_']
    

    注意,我们现在有两个主键了,一个是MongoDB自带的”_id“,另一个是我们新增的”user_id“。

    现在,我们来新增一些用户信息:

    >>> user_profiles = [
    ...     {'user_id': 211, 'name': 'Luke'},
    ...     {'user_id': 212, 'name': 'Ziltoid'}]
    >>> result = db.profiles.insert_many(user_profiles)
    

    我们新增的主键阻止我们新增一条已存在这个主键的记录。

    >>> new_profile = {'user_id': 213, 'name': 'Drew'}
    >>> duplicate_profile = {'user_id': 212, 'name': 'Tommy'}
    >>> result = db.profiles.insert_one(new_profile)  # This is fine.
    >>> result = db.profiles.insert_one(duplicate_profile)
    Traceback (most recent call last):
    pymongo.errors.DuplicateKeyError: E11000 duplicate key error index: test_database.profiles.$user_id_1 dup key: { : 212 }
    

    写在最后

    官方文档上并没有给出删除,修改记录的方法,或许是我目前还没看到吧,等看到了我会再补充上来的。文档比较短,翻译的过程中由于本人英语水平有限,并不能做到逐字逐句的翻译,也无法保证完全准确,并且会有一些地方的内容念起来并不是那么的顺口,但是官方文档想表达的大概意思应该是不会错的。

    相关文章

      网友评论

        本文标题:Python-MongoDB翻译

        本文链接:https://www.haomeiwen.com/subject/pjiflttx.html