本文实例讲述了Python常见MongoDB数据库操作。分享给大家供大家参考,具体如下:
MongoDB 是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能。接下来记录一下在使用PyMongo操作MongoDB
下载pymongo库
1
|
pip install pymongo
|
前置操作
1
2
3
4
5
6
|
# 获取MongoDB操作,localhost为host,27017为MongoDB默认port
client = pymongo.MongoClient( "mongodb://localhost:27017/" )
# 操作test数据库
db = client.test
# 获取Student集合
student = db.Student
|
插入单条数据
1
2
3
4
5
|
# 插入一条数据,并获取返回结果
res = student.insert_one({ "name" : "老王" })
# 获取插入之后该条数据的id
object_id = res.inserted_id
print (object_id)
|
插入多条数据
1
2
3
4
5
|
# 插入9条数据
res = student.insert_many([{ "name" : "name%d" % index} for index in range ( 1 , 10 )])
# 获取插入之后该9条数据的ids,object_ids为一个list
object_ids = res.inserted_ids
print (object_ids)
|
查询单条数据
1
2
|
# 查询单条数据,res为一个dict
res = student.find_one({ "name" : "老王" })
|
查询满足条件的所有数据
1
2
3
4
5
6
7
|
# 查询满足条件的所有数据,res为一个pymongo.cursor.Cursor对象
res = student.find({ "name" : "老王" })
# 获取数据个数
print (res.count())
for index in res:
# index为一个dict。注意:这个循环只能进行一次,如需再次操作返回结果,需要在find一次,或将list(res),将这个返回结果保存起来
print (index)
|
更新
1
2
3
|
# 查询并更新。{"name":"老王"}为查询条件;{"$set":{"addr":"家住隔壁"}}更新数据;upsert=False找不到不插入数据,upsert=True找不到则插入数据
# res为返回结果,res为一个字典对象,是之前数据的字典
res = student.find_one_and_update({ "name" : "老王" },{ "$set" :{ "addr" : "家住隔壁" }},upsert = False )
|
删除单条数据
1
|
student.delete_one({ "name" : "老王" })
|
删除匹配条件的所有数据
1
|
student.delete_many({ "name" : "老王" })
|
附:更多MongoDB的操作
MongoDB 是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能。接下来记录一下在终端怎么使用MongoDB:
常用命令
切换/创建数据库
1
|
use xxx; # 切换数据库,不存在则创建
|
插入数据
1
2
|
# 插入数据,name="Python",age=100,Student为集合(表)名,Student不存在会自动创建
db.Student.insert({name: "Python" ,age: 100 })
|
或者定义一个字典
1
2
|
document = {name: "Python" ,age: 100 }
db.Student.insert(document)
|
查询数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
# 查询所有数据
db.Student.find()
# 查询所有数据并格式化输出
db.Student.find().pretty()
# 条件查询,name="python"的所有数据
db.Student.find({name: "python" })
# 条件查询,age > 50的所有数据
db.Student.find({age:{$gt: 50 }})
# 条件查询,age >= 50的所有数据
db.Student.find({age:{$gte: 50 }})
# 条件查询,age < 50的所有数据
db.Student.find({age:{$lt: 50 }})
# 条件查询,age <= 50的所有数据
db.Student.find({age:{$lte: 50 }})
# 条件查询,age == 50的所有数据
db.Student.find({age:{$eq: 50 }})
# 条件查询,age != 50的所有数据
db.Student.find({age:{$ne: 50 }})
# 条件查询,存在name字段的所有数据
db.Student.find({name:{$exists:true}})
# 多条件查询,name="python"并且age=50的所有数据
db.Student.find({name: "python" ,age: 50 })
# $and语法,name="python"并且age=50的所有数据。
db.Student.find({$ and :[{name: "python" },{age: 50 }]})
# 查询字典数组的数据infoList = [{"province":"广东","city":"深圳"}]
db.Student.find({ "infoList.province" : "广东" })
# 查询数量
db.Student.find({name: "python" }).count()
# 或查询,$or语法。查询name="python"或name="android"的所有数据
db.Student.find({$ or :[{name: "python" },{name: "android" }]})
# $size语法,查询info数组长度为8的所有数据
db.Student.find({info:{$size: 8 }})
# $not语法,查询info数组长度不为8的所有数据
db.Student.find({info:{$ not :{$size: 8 }}})
# and与or联合使用.相当于 where age=18 and (name="python" or name="android")
db.Student.find({age: 18 ,$ or :[{name: "python" },{name: "android" }]})
# $nor语法,搜索name既不等于"python"且不等于"android"的所有数据
db.Student.find({ "$nor" :[{name: "python" },{name: "android" }]})
# $in语法.搜索name="老张"或name="老王"的所有数据
db.Student.find({name:{$ in :[ "老王" , "老张" ]}})
# $nin语法.搜索name不为"老张"或"老王"的所有数据
db.Student.find({name:{$nin:[ "老王" , "老张" ]}})
# $all语法,搜索info=["aaa","bbb"]的所有数据
db.Student.find({info:{$ all :[ "aaa" , "bbb" ]}})
# $mod语法,搜索sex % 2 == 0的所有数据
db.Student.find({sex:{$mod:[ 2 , 0 ]}})
# $where语法,搜索age=info的所有数据
db.Student.find({ "$where" : "this.age==this.info" })
# $slice语法,过滤,info数组中的后3个数据
db.Student.find({},{info:{$ slice : - 3 }})
# $slice语法,过滤,info数组中的前3个数据
db.Student.find({},{info:{$ slice : 3 }})
# $slice语法,过滤,info数组中跳过20个数据之后取10个数据
db.Student.find({},{info:{$ slice :[ 20 , 10 ]}})
# $slice语法,过滤,info数组中倒数第20个数据之后取10个数据
db.Student.find({},{info:{$ slice :[ - 20 , 10 ]}})
# 正则.获取name包含"王"的所有数据
db.Student.find({name:{$regex: "王" }})
# 正则。获取name包含"a"并且不区分大小写的所有数据
db.Student.find({name:{$regex: "a" ,$options: "i" }})
|
更新数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# 找到name="MongoDB"的数据,将其更改为name="MongoDB学习",只修改匹配到的第一条数据
db.Student.update({name: "MongoDB" },{$ set :{name: "MongoDB学习" }})
# 找不到name="MongoDB"的数据,则插入name="MongoDB学习",找到了则为修改。upsert:true找不到则插入,默认false,不插入
db.Student.update({name: "MongoDB" },{$ set :{name: "MongoDB学习" }},{upsert:true})
# 找到name="MongoDB"的数据,将其更改为name="MongoDB学习"。multi:true更改所有匹配的数据,默认false,只匹配第一条
db.Student.update({name: "MongoDB" },{$ set :{name: "MongoDB学习" }},{multi:true})
# 匹配name="MongoDB"的第一条数据,将其更改为name="MongoDB学习"
db.Student.updateOne({name: "MongoDB" },{$ set :{name: "MongoDB学习" }})
# 更新字典数组的数据infoList = [{"province":"广东","city":"深圳"}]
db.Student.update({ "infoList.province" : "广东" },{ "$set" :{ "province.$.city" : "广州" }})
# 将age>18的数据,修改name="xxx",第一个false:不存在不会插入(true为不存在则插入),第二个false:只匹配第一条数据(true为匹配所有数据)
db.Student.update({age:{$gt: 18 }},{$ set :{name: "xxx" }},false,false)
# 在name="python"的所有数据里,将age字段值+1
db.Student.update({name: "python" },{$inc:{age: 1 }})
# 在name="python"的所有数据里,将age键删除,1可以是任何值
db.Student.update({name: "python" },{$unset:{age: 1 }})
# 在name="python"的所有数据里,将age键名修改成"Age"
db.Student.update({name: "python" },{$rename:{age: "Age" }})
# 在name="python"的所有数据里,在名为array的数组添加abc元素
db.Student.update({name: "python" },{$push:{array: "abc" }})
# 在name="python"的所有数据里,将["abc","adc"]里所有元素添加到array里面
db.Student.update({name: "python" },{$pushAll:{array:[ "abc" , "adc" ]}})
# 在name="python"的所有数据里,在名为array的数组删除abc元素
db.Student.update({name: "python" },{$pull:{array: "abc" }})
# 在name="python"的所有数据里,将["abc","adc"]里所有元素全部从array里删除
db.Student.update({name: "python" },{$pullAll:{array:[ "abc" , "adc" ]}})
# 在name="python"的所有数据里,删除array数组尾部数据,无论array为多少都只删除一条,array小于0时,删除头部第一条,array大于等于0时,删除尾部第一条
db.Student.update({name: "python" },{$pop:{array: 2 }})
|
删除数据
1
2
3
4
|
# 删除匹配到的所有数据
db.Student.remove({name: "老张" })
# 删除匹配到第一条数据,justOne:true只删除一条数据
db.Student.remove({name: "老张" },{justOne:true})
|
**type**:type**:type操作符是基于BSON类型来检索集合中匹配的数据类型,并返回结果
常用type类型:
数字 | 类型 |
---|---|
1 | Double |
2 | String |
3 | Object |
4 | Array |
5 | Binary data |
6 | Undefined |
7 | Object id |
8 | Boolean |
9 | Date |
10 | Null |
11 | Regular Expression |
13 | JavaScript |
14 | Symbol |
15 | JavaScript (with scope) |
16 | 32-bit integer |
17 | Timestamp |
18 | 64-bit integer |
255 | Min key |
127 | Max key |
1
2
|
# 查询name为String类型的所有数据,2为String
db.Student.find({name:{$ type : 2 }})
|
- limit:限制条数
1
2
|
# 查询name="python"的所有数据,限制2条
db.Student.find({name: "python" }).limit( 2 )
|
- skip:跳过数据
1
2
|
# 查询name > 15的数据,跳过前两条,并限制只查询两条
db.Student.find({name:{$gt: 15 }}).limit( 2 ).skip( 2 )
|
- sort:排序,1位升序,-1位降序
1
2
3
4
|
# 查询所有数据,并以age升序排列
db.Student.find().sort({age: 1 })
# 多条件排序
db.Student.find().sort({age: 1 ,score: - 1 })
|
- findAndModify:查找并更新
1
2
|
# 查找name="python"的所有数据,并修改age=18
db.Student.findAndModify({query:{name: "python" },update:{$ set :{age: 18 }}})
|
- ObjectId
1
2
|
# 获取文档的创建时间
ObjectId( "598542475e6b2464187abef7" ).getTimestamp()
|
- aggregate:聚合查询
常用聚合表达式:
表达式 | 描述 |
---|---|
$sum | 和 |
$avg | 平均值 |
$min | 最小值 |
$max | 最大值 |
$push | 在结果中插入值到数组中 |
$addToSet | 在结果中插入值到数组中,但不创建副本 |
$first | 根据资源文档的排序,获取第一个数据 |
$last | 根据资源文档的排序,获取最后一个数据 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
# 根据name分组,并插入sum,sum值为该组所有age的和
db.Student.aggregate([{$group:{_id: "$name" , sum :{$ sum : "$age" }}}])
# 根据name分组,并插入sum,sum值为该组的数量,并以sum排序,升序
db.Student.aggregate([{$group:{_id: "$name" , sum :{$ sum : 1 }}}])
# 根据name分组,并插入avg,avg值为该组所有age的平均值
db.Student.aggregate([{$group:{_id: "$name" ,avg:{$avg: "$age" }}}])
# 根据name分组,并插入min,min值为该组所有age的最小值
db.Student.aggregate([{$group:{_id: "$name" , min :{$ min : "$age" }}}])
# 根据name分组,并插入max,max值为该组所有age的最大值
db.Student.aggregate([{$group:{_id: "$name" , max :{$ max : "$age" }}}])
# 根据name分组,并插入数组array,array值为该组所有的age值
db.Student.aggregate([{$group:{_id: "$name" ,array:{$push: "$age" }}}])
# 根据name分组,并插入数组array,array值为该组所有的age值
db.Student.aggregate([{$group:{_id: "$name" ,array:{$addToSet: "$age" }}}])
# 根据name分组,并插入f,f值为该组age下的第一个值
db.Student.aggregate([{$group:{_id: "$name" ,f:{$first: "$age" }}}])
# 根据name分组,并插入l,l值为该组age下的第一个值
db.Student.aggregate([{$group:{_id: "$name" ,l:{$last: "$age" }}}])
|
管道操作实例
1. $project:用于修改文档的输出结构
1
2
|
# 查询所有的name,age数据,默认包含_id数据。让不包含_id,可以使_id:0
db.Student.aggregate({$project:{name: 1 ,age: 1 }})
|
此时输出的内容只有_id,name,age,_id是默认会输出的,想不输出_id,可以使_id:0
2. $match:用于过滤数据
1
|
db.Student.aggregate([{$match:{age:{$gt: 19 ,$lte: 23 }}},{$group:{_id:null,count:{$ sum : 1 }}}])
|
match过滤出age大于19且小于等于23的数据,然后将符合条件的记录送到下一阶段match过滤出age大于19且小于等于23的数据,然后将符合条件的记录送到下一阶段group管道操作符进行处理
3. $skip:将前5个过滤掉
1
|
db.Student.aggregate({$skip: 5 })
|
$skip将前面5个数据过滤掉
希望本文所述对大家Python程序设计有所帮助。
原文链接:https://blog.csdn.net/y472360651/article/details/75911830