
MongoDB是由C++语言编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,其内容存储形式类似于JSON对象,它的字段值可以包含其他文档,数组以及文档数组,非常灵活。
1、准备工作
确保电脑安装了MongoDB并启动了其服务,并且安装了PyMongo库,本文不做介绍。
2、连接MongoDB
连接MongoDB是,需要哦使用PyMongo库中的MongoClient。
import pymongo
#client = pymongo.MongoClient(host='127.0.0.1', port=27017)
client = pymongo.MongoClient('mongodb://127.0.0.1:27017/')
#两种写法都可以达到相同的连接效果3、指定数据库
MongoDB中可以建立多个数据库,需要指定操作的数据库。
db = client.test
#db = client['test]
#两种方法等价4、指定集合
MongoDB的每个数据库又包含许多集合(collection),类似于关系型数据库中的表。与指定数据库类似。
collection = db.students
#collection = db['students']这样我们便声明了一个Collection对象
5、插入数据
新建一条学生数据,以字典形式表示:
student = {
'id':'20170104',
'name':'Tomr',
'age':20,
'gender':'male'
}这里指定了学生的学号、姓名、年龄和性别。直接调用collection的insert()方法即可插入数据
res = collection.insert(student)
print(res)在MongoDB中,每条数据都有一个_id属性来唯一标识。如果没有显式指明该属性,MongoDB会自动产生一个ObjectId类型的 _id属性。insert()方法会执行后返回 _id值
运行结果如下
5cb1ea2230f1f4dfdcfa9234还可同时插入多条数据,只需要以列表形式传递即可。
student = {
'id':'20170104',
'name':'Tomr',
'age':20,
'gender':'male'
}
student1 = {
'id':'20170102',
'name':'Mike',
'age':25,
'gender':'male'
}
res = collection.insert([student,student1])
print(res)
#返回结果是对应的 _id集合
[ObjectId('5cb1eab130f1f4dc848730da'), ObjectId('5cb1eab130f1f4dc848730db')]官方推荐使用insert_one()和insert_many()方法分别插入单条记录和多条记录。
student = {
'id':'20170104',
'name':'Tomr',
'age':20,
'gender':'male'
}
res = collection.insert_one(student)
print(res)
print(res.inserted_id)
#运行结果
<pymongo.results.InsertOneResult object at 0x0000019DF8C92C88>
5cb1eb5e30f1f4e04005dbfd与insert()方法不同,返回的是InsertOneResult对象,调用其inserted_id属性获取 _id
对于insert_many()方法,将数据以列表形式传递。
student = {
'id':'20170104',
'name':'Tomr',
'age':20,
'gender':'male'
}
student1 = {
'id':'20170102',
'name':'Mike',
'age':25,
'gender':'male'
}
res = collection.insert_many([student,student1])
print(res)
print(res.inserted_ids)
#运行结果
<pymongo.results.InsertManyResult object at 0x000001A658EC95C8>
[ObjectId('5cb1ec1b30f1f4c0fcb7a87b'), ObjectId('5cb1ec1b30f1f4c0fcb7a87c')]返回的类型是InsertManyResult对象,调用inserted_ids属性可以获取插入数的 _id列表
6、查询
查询使用find_one()或find()方法进行查询,其中find_one()查询得到的是单个结果,find()则返回一个生成器对象。
res = collection.find_one({'name':'Mike'})
print(type(res))
print(res)
返回结果是字典类型,运行结果如下
<class 'dict'>
{'_id': ObjectId('5cb1a00330f1f4aac47fad27'), 'id': '20170102', 'name': 'Mike', 'age': 25, 'gender': 'male'}
也可以根据ObjectId来查询,此时需要使用bson库里面的objectid
from bson.objectid import ObjectId
res = collection.find_one({'_id':ObjectId('5cb1a00330f1f4aac47fad27')})
print(type(res))
print(res)
#运行结果
<class 'dict'>
{'_id': ObjectId('5cb1a00330f1f4aac47fad27'), 'id': '20170102', 'name': 'Mike', 'age': 25, 'gender': 'male'}
如果查询结果不存在,则返回None
查询多条数据使用find()
res = collection.find({'age':20})
print(type(res))
print(res)
for item in res:
print(item)
#运行结果
<class 'pymongo.cursor.Cursor'>
<pymongo.cursor.Cursor object at 0x000001C8D596FD68>
{'_id': ObjectId('5cb19fa930f1f4aa3c2439d5'), 'id': '20170101', 'name': 'Tom', 'age': 20, 'gender': 'male'}
{'_id': ObjectId('5cb1a00330f1f4aac47fad26'), 'id': '20170104', 'name': 'Tomr', 'age': 20, 'gender': 'male'}
{'_id': ObjectId('5cb1a03a30f1f4a55459e359'), 'id': '20170104', 'name': 'Tomr', 'age': 20, 'gender': 'male'}
返回结果是Cursor类型,相当于一个生成器。
查询年龄大于20的数据
res = collection.find({'age':{'$gt':20}})
比较符号归纳如下
| 符号 | 含义 | 示例 |
|---|---|---|
| $lt | 小于 | {‘age':{'$lt':20}} |
| $gt | 大于 | {‘age':{'$gt':20}} |
| $lte | 小于等于 | {‘age':{'$lte':20}} |
| $gte | 大于等于 | {‘age':{'$gte':20}} |
| $ne | 不等于 | {‘age':{'$ne':20}} |
| $in | 在范围内 | {‘age':{'$in':[20,30]}} |
| $nin | 不在范围内 | {‘age':{'$nin':[20,30]}} |
还可以进行正则匹配查询,例如查询名字以M开头的学生数据,示例如下:
res = collection.find({'name':{'$regex':'^M.*'}})
for item in res:
print(item)
| 符号 | 含义 | 示例 | 示例含义 |
|---|---|---|---|
| $regex | 匹配正则表达式 | {'name':{'$regex':'^M.*'}} | name以M开头 |
| $exists | 属性是否存在 | {'name':{'$exists':True}} | name属性存在 |
| $type | 类型判断 | {'age':{'$type':'int'}} | age的类型为int |
| $mod | 数字模操作 | {'age':{'$mod':[5,0]}} | 年龄模5余0 |
| $text | 文本查询 | {'$text':{'$search':'Mike'}} | text类型的属性中包含Mike字符串 |
| $where | 高级条件查询 | {'$where':'obj.fans_count==obj.follows_count'} | 自身粉丝数等于关注数 |
7、计数
统计查询结果,可以调用count()方法
res = collection.find().count()
print(res)
#运行结果
12
统计符合条件的数据总数
res = collection.find({'name':{'$regex':'^M.*'}}).count()
print(res)
#运行结果
4
8、排序
直接调用sort()方法,并在其中传入排序的字段以及升降序标志即可
res = collection.find().sort('name', pymongo.ASCENDING)
print([item['name'] for item in res])
#运行结果
['Mike', 'Mike', 'Mike', 'Mike', 'Tom', 'Tomr', 'Tomr', 'Tomr', 'Tomr', 'Tomr', 'Tomr', 'Tomr']
其中pymongo.ASCENDING指定升序,pymongo.DESCENDING指定降序
9、偏移
只是查询几个元素,可以使用skip()方法便宜几个位置,比如偏移3,就忽略前三个元素,得到第四个以后的元素
res = collection.find().sort('name', pymongo.ASCENDING).skip(3)
print([item['name'] for item in res])
#运行结果
['Mike', 'Tom', 'Tomr', 'Tomr', 'Tomr', 'Tomr', 'Tomr', 'Tomr', 'Tomr']
还可以使用limit()方法指定要取结果个数,
res = collection.find().sort('name', pymongo.ASCENDING).skip(3).limit(2)
print([item['name'] for item in res])
#运行结果
['Mike', 'Tom']
注意的是,在数据库数量非常庞大的时候,如千万,亿级别,最好不要使用大的派年以来来查询数据,可能会导致内存溢出,可以类似如下操作查询。
from bson.objectid import ObjectId
res = collection.find_one({'_id':{'$gt': ObjectId('5cb1a00330f1f4aac47fad27')}})
这时需要记录上次查询的 _id。
10、更新
数据更新可以使用update()方法,指定更新的条件和更新后的数据即可。
condition = {'name':'Tom'}
st = collection.find_one(condition)
print('更新前')
print(st)
st['age'] = 20
res = collection.update(condition, st)
print(res)
print('更新后')
st = collection.find_one(condition)
print(st)
#运行结果
更新前
{'_id': ObjectId('5cb19fa930f1f4aa3c2439d5'), 'id': '20170101', 'name': 'Tom', 'age': 25, 'gender': 'male'}
res = collection.update(condition, st)
{'n': 1, 'nModified': 1, 'ok': 1.0, 'updatedExisting': True}
更新后
{'_id': ObjectId('5cb19fa930f1f4aa3c2439d5'), 'id': '20170101', 'name': 'Tom', 'age': 20, 'gender': 'male'}
更新结果返回字典形式,ok代表执行成功,nModified代表影响的数据条数。
也可以使用$set操作符对数据进行更新
res = collection.update(condition, {'$set',st})
这样可以只更新st字典中存在的字段,如果原先还有其他字段,则不hi更新,也不会删除。而不用$set,则会把之前的数据全部用st字典替换,原本存在其他字段,则会被删除。
官方推荐使用update_on()和update_many()方法,用法更加严格。它们的第二个参数需要使用$类型操作符作为字典的键名。
st['age'] = 30
#res = collection.update(condition, st)
#res = collection.update(condition, {'$set',st})
res = collection.update_one(condition, {'$set':st})
print(res)
print(res.matched_count, res.modified_count)
#结果
<pymongo.results.UpdateResult object at 0x00000188BDA89B88>
1 1
第二个参数不能直接传入修改后的字典,俄日是需要使用{'$set':st}这样的形式,返回结构是UpdateResult类型,分别调用matched_count和modified_count属性,可以获得匹配的数据条数和影响的数据条数。
condition = {'age':{'$gt':20}}
res = collection.update_one(condition, {'$inc':{'age':1}})
print(res)
print(res.matched_count, res.modified_count)
#结果
<pymongo.results.UpdateResult object at 0x00000243ACB70308>
1 1
指定查询条件为年龄大于20,更新条件为{'$inc':{'age':1},也就是年龄加1,执行之后将第一条符合条件的数据年龄加1。
调用update_many()方法,则将所有符合条件的数据都更新
condition = {'age':{'$gt':20}}
res = collection.update_many(condition, {'$inc':{'age':1}})
print(res)
print(res.matched_count, res.modified_count)
#运行结果
<pymongo.results.UpdateResult object at 0x00000206A9C89608>
5 5
11、删除
删除操作比较简单。直接使用remove()方法指定删除的条件即可,符合条件的所有数均会被删除。
res = collection.remove({'name':'Tom'})
print(res)
#运行结果
{'n': 1, 'ok': 1.0}
还可使用推荐方法delete_one()和delete_many().
res = collection.delete_one({'name':'Mike'})
print(res)
print(res.deleted_count)
res = collection.delete_many({'age':{'$lt':30}})
print(res)
print(res.deleted_count)
运行结果
<pymongo.results.DeleteResult object at 0x0000019068652848>
1
5
delete_one()删除第一条符合条件的数据,delete_many()删除所有符合条件的数据,返回结果都是DeleteResult类型,可以调用delete_count()属性获取删除的数据条数.
12、其他操作
PyMongo还提供了一些组合方法,如find_one_and_delete(),find_one_and_replace()和find_one_and_update()表示查找后删除,替换,更新操作,用法一致。
还可以对索进行操作,有create_index(),create_indexes()和drop_index()
评论(1)