Python3 操作 MongoDB

一、安装

pip3 install pymongo

二、基本使用

1. 导入模块

import pymongo

2. 建立本地链接

cl = pymongo.MongoClient('localhost', 27017)

# 或者

cl = Mongocl('mongodb://localhost:27017/')


3. 获取数据库

一个MongoDB实例可以支持多个独立的 数据库。在使用PyMongo时,您可以使用Mongocl实例上的属性样式访问来访问数据库:

# 查看当前都有那些库
cl.database_names()

# 获取数据库对象
db = cl.test_database

或者

db = cl['test_database']


4. 获取集合

一个集合是一组存储在MongoDB中的文档,并且可以被认为是大致在关系数据库中的表。
在 PyMongo 中获取集合与获取数据库的工作方式相同:

# 查看当前库中都有那些集合
db.collection_names()

# 获取集合对象
collection = db.test_collection

# 或者

collection = db['test-collection']

合法的集合名:

  • 集合名不能是空字符串""。
  • 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
  • 集合名不能以"system."开头,这是为系统集合保留的前缀。
  • 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。

三、惰性机制

关于MongoDB中的集合(和数据库)的一个重要注意事项是它们是懒惰地创建的。
上述命令都没有在MongoDB服务器上实际执行过任何操作。集合和数据库在第一个文档被插入时创建。

四、 文档

MongoDB中的数据使用JSON样式的文档来表示(并存储)。
在PyMongo中,我们使用字典来表示 Mongo 中文档。例如,以下字典可能用于表示博客文章:

In [34]: import datetime

In [35]: post = {"author": "yangge",
        "text": "云计算-NoSQL",
        "tags": ["mongodb", "python", "pymongo"],
        "date": datetime.datetime.now()}

请注意,文档可以包含本机Python类型(如datetime.datetime实例),这些类型 将自动转换为适当的BSON类型并从其中转换

文档特点:

  • 文档中的键/值对是有序的。
  • 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
  • MongoDB区分类型和大小写。
  • MongoDB的文档不能有重复的键。
  • 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。

文档键命名规范:

  1. 键不能含有\0 (空字符)。这个字符用来表示键的结尾。
  2. .和$有特别的意义,只有在特定环境下才能使用。
  3. 以下划线"_"开头的键是保留的(不是严格要求的)。

五、 插入文件数据

# 使用、创建了 posts 集合
In [36]: posts_col = db.posts 

# 向 psts 集合中插入一个文档,并返回了 _id 对象
In [37]: post_id = posts_col.insert_one(post).inserted_id

In [38]: post_id
Out[38]: ObjectId('5a9f8eb2e138232b02854093')

In [41]: print(post_id)
5a9f8eb2e138232b02854093

In [42]: post_id.__str__()
Out[42]: '5a9f8eb2e138232b02854093'

验证

插入第一个文档后,posts集合实际上已经在服务器上创建。

我们可以通过列出数据库中的所有集合来验证这一点:

In [45]: db.collection_names(include_system_collections=False)
Out[45]: ['posts_col']

六、 使用find_one()获取单个文档

可以在MongoDB中执行的最基本的查询类型是 find_one()。

此方法返回与查询匹配的单个文档(如果没有匹配,则返回None)。

当您知道只有一个匹配的文档,或者只对第一个匹配感兴趣时,它非常有用。

这里我们使用 find_one()从posts集合中获取第一个文档:

In [47]: posts_col.find_one()
Out[47]:
{'_id': ObjectId('5a9f8a6de138232b02854092'),
 'author': 'Mike',
 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': 'My first blog post!'}

指定匹配查询

In [47]: posts_col.find_one(post)
Out[47]:
{'_id': ObjectId('5a9f8eb2e138232b02854093'),
 'author': 'yangge',
 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': '云计算-NoSQL'}
 # --------------------------------------------------
 
 In [88]: posts_col.find_one({'author': 'yangge'})
Out[88]:
{'_id': ObjectId('5a9f8eb2e138232b02854093'),
 'author': 'yangge',
 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000),
 'tags': ['mongodb', 'python', 'pymongo'],
 'text': '云计算-NoSQL'}

最好通过 _id_obj 查找

假如你创建了同样的数据在 Mongo 里,他会同时存在,但是 _id 不一样。

所以建议使用创建数据时返回的 _id 对象来查询。

In [93]: posts_col.insert_one({"shark": "鲨鱼"}).inserted_id
Out[93]: ObjectId('5a9f97d1e138232b02854094')

In [94]: posts_col.insert_one({"shark": "鲨鱼"})
Out[94]: <pymongo.results.InsertOneResult at 0x7f74d652e388>

In [95]: shark_id = posts_col.insert_one({"shark": "鲨鱼", "age": "18"}).inserted_id

In [96]: shark_id_obj = posts_col.insert_one({"shark": "鲨鱼"}).inserted_id

In [97]: posts_col.find_one({"_id": shark_id_obj})
Out[97]: {'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鲨鱼'}

In [98]: posts_col.find_one({"_id": shark_id})
Out[98]: {'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鲨鱼'}

# 注意有个空格哦
In [99]: posts_col.find_one({"shark": " 鲨鱼"})

In [100]: posts_col.find_one({"shark": "鲨鱼"})
Out[100]: {'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鲨鱼'}

从字符串转换为ObjectId

In [121]: from bson.objectid import ObjectId

In [122]: posts_col.find_one({'_id': ObjectId(shark_id_obj)})
Out[122]: {'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鲨鱼'}

==在 Python2 中==

MongoDB以BSON格式存储数据。BSON字符串是UTF-8编码的,所以PyMongo必须确保它存储的任何字符串只包含有效的UTF-8数据。常规字符串(<type'str'>)被验证并保存不变。Unicode字符串(<type'unicode'>)首先被编码为UTF-8。我们的示例字符串在Python shell中被表示为u'Mike'而不是'Mike',原因是PyMongo将每个BSON字符串解码为Python unicode字符串,而不是常规str。

关于 _id

In [110]: shark_id.generation_time.isoformat()
Out[110]: '2018-03-07T07:42:50+00:00'

七、 批量插入

为了让查询更有趣,让我们插入更多的文档。除了插入单个文档外,我们还可以通过将列表作为第一个参数传递给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_col.insert_many(new_posts)
>>> result.inserted_ids
[ObjectId('...'), ObjectId('...')]

查询多个文档

我们使用find() 方法来获取多个文档 。
find() 返回一个 Cursor实例,它允许我们遍历所有匹配的文档。

例如,我们可以迭代posts集合中的每个文档:

In [129]: for post in posts_col.find():
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f8a6de138232b02854092'), 'author': 'Mike', 'text': 'My first blog post!', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000)}
{'_id': ObjectId('5a9f8eb2e138232b02854093'), 'author': 'yangge', 'text': '云计算-NoSQL', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000)}
{'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鲨鱼'}
{'_id': ObjectId('5a9f97e1e138232b02854095'), 'shark': '鲨鱼'}
{'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鲨鱼'}
{'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鲨鱼'}
{'_id': ObjectId('5a9f9e48e138232b02854098'), 'author': 'Mike', 'text': 'Another post!', 'tags': ['bulk', 'insert'], 'date': datetime.datetime(2009, 11, 12, 11, 14)}
{'_id': ObjectId('5a9f9e48e138232b02854099'), 'author': 'Eliot', 'title': 'MongoDB is fun', 'text': 'and pretty easy too!', 'date': datetime.datetime(2009, 11, 10, 10, 45)}

就像我们用 find_one()所做的那样,我们可以传递一个文档给 find() 来限制返回的结果。
在这里,我们只得到那些作者是 "鲨鱼" 的文档:

In [133]: for post in posts_col.find({"shark": '鲨鱼'}):
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f97d1e138232b02854094'), 'shark': '鲨鱼'}
{'_id': ObjectId('5a9f97e1e138232b02854095'), 'shark': '鲨鱼'}
{'_id': ObjectId('5a9f97fae138232b02854096'), 'shark': '鲨鱼'}
{'_id': ObjectId('5a9f9807e138232b02854097'), 'shark': '鲨鱼'}

计数

In [134]: posts_col.count()
Out[134]: 8

In [135]: posts_col.find({"author": "yangge"}).count()
Out[135]: 1

范围查询

MongoDB支持许多不同类型的高级查询。例如,让我们执行查询,将结果限制为比特定日期更早的帖子,还可以按作者对结果进行排序

In [136]: d = datetime.datetime(2018, 11, 12, 12)

In [137]:  for post in posts_col.find({"date": {"$lt": d}}).sort("author"):
     ...:     print(post)
     ...:
{'_id': ObjectId('5a9f9e48e138232b02854099'), 'author': 'Eliot', 'title': 'MongoDB is fun', 'text': 'and pretty easy too!', 'date': datetime.datetime(2009, 11, 10, 10, 45)}
{'_id': ObjectId('5a9f8a6de138232b02854092'), 'author': 'Mike', 'text': 'My first blog post!', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 6, 44, 54, 672000)}
{'_id': ObjectId('5a9f9e48e138232b02854098'), 'author': 'Mike', 'text': 'Another post!', 'tags': ['bulk', 'insert'], 'date': datetime.datetime(2009, 11, 12, 11, 14)}
{'_id': ObjectId('5a9f8eb2e138232b02854093'), 'author': 'yangge', 'text': '云计算-NoSQL', 'tags': ['mongodb', 'python', 'pymongo'], 'date': datetime.datetime(2018, 3, 7, 15, 1, 0, 355000)}

排序

db.mycollection
mycol = db.mycollection
mycol.insert_one({'name': '姜文'})
result_dic = db.mycollection.find().sort("age")
for item in result_dic:
    print(item)

更新

更新数据库, ObjectId 需要引入

from bson.objectid import ObjectId
db.mycollection.update({'_id': ObjectId('59255118d92fac43dcb1999a')}, {'$set': {'name': '九筒'}})

删除

删除指定数据

db.mycollection.remove({'name':'王二麻33333'})

删除全部数据(慎用)

db.mycollection.remove()

### capped collections (扩展)

Capped collections 就是固定大小的collection。

它有很高的性能以及队列过期的特性(过期按照插入的顺序). 有点和 "RRD" 概念类似。

Capped collections是高性能自动的维护对象的插入顺序。它非常适合类似记录日志的功能 和标准的collection不同,你必须要显式的创建一个capped collection, 指定一个collection的大小,单位是字节。collection的数据存储空间值提前分配的。

要注意的是指定的存储大小包含了数据库的头信息。

db.createCollection("mycoll", {capped:true, size:100000})
  • 在capped collection中,你能添加新的对象。
  • 能进行更新,然而,对象不会增加存储空间。如果增加,更新就会失败 。
  • 数据库不允许进行删除。使用drop()方法删除collection所有的行。
  • 注意: 删除之后,你必须显式的重新创建这个collection。
  • 在32bit机器中,capped collection最大存储为1e9( 1X109)个字节。

元数据

数据库的信息是存储在集合中。它们使用了系统的命名空间:

dbname.system.*

在MongoDB数据库中名字空间 <dbname>.system.* 是包含多种系统信息的特殊集合(Collection),如下:

集合命名空间描述
dbname.system.namespaces列出所有名字空间。
dbname.system.indexes列出所有索引。
dbname.system.profile包含数据库概要(profile)信息。
dbname.system.users列出所有可访问数据库的用户。
dbname.local.sources包含复制对端(slave)的服务器信息和状态。

对于修改系统集合中的对象有如下限制。

  • {{system.indexes}} 插入数据,可以创建索引。

  • 但除此之外该表信息是不可变的(特殊的 drop index 命令将自动更新相关信息)。

  • {{system.users}} 是可修改的。

  • {{system.profile}} 是可删除的。


MongoDB 数据类型

下表为MongoDB中常用的几种数据类型。

数据类型描述
String字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean布尔值。用于存储布尔值(真/假)。
Double双精度浮点值。用于存储浮点值。
Min/Max keys将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Array用于将数组或列表或多个值存储为一个键。
Timestamp时间戳。记录文档修改或添加的具体时间。
Object用于内嵌文档。
Null用于创建空值。
Symbol符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID对象 ID。用于创建文档的 ID。
Binary Data二进制数据。用于存储二进制数据。
Code代码类型。用于在文档中存储 JavaScript 代码。
Regular expression正则表达式类型。用于存储正则表达式。


 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值