avatar

目录
MongoDB(by python)

参考:heima

[TOC]

介绍&安装

关系型缺点

  • 扩展性差、大数据下IO压力大、表结构更改困难

MongoDB优点

  • 易扩展、大数据量,高性能、灵活的数据模型

安装:centos+yum安装mongodb

sh
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
# 配置MongoDB的yum源
$ vim /etc/yum.repos.d/mongodb-org-3.4.repo
#添加以下内容:
[mongodb-org-3.4]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/3.4/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.4.asc


$ yum makecache
$ yum -y install mongodb-org
# 查看mongo安装位置
$ whereis mongod
# 查看修改配置文件 :
$ vim /etc/mongod.conf
# 启动mongodb :
$ systemctl start mongod.service
# 启动Mongo shell
$ mongo
# 查看数据库:
> show dbs
# 退出
> exit

基本操作

  • 关于database的基础命令
  • 关于集合的基础命令
  • 数据类型
sh
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
# 1、关于database的基础命令
# 查看当前的数据库:
> db
# 查看所有的数据库:
> show dbs
# 切换数据库:
> use db_name
# 删除当前的数据库:
> db.dropDatabase()
# 不用创建数据库,插数据时会自动创建

# 2、关于集合的基础命令
# 不手动创建集合:
# 向不存在的集合中第⼀次加⼊数据时, 集合会被创建出来
# 手动创建结合:
> db.createCollection(name,options)
> db.createCollection("stu")
> db.createCollection("sub", { capped : true, size : 10 } )
# 参数capped: 默认值为false表示不设置上限,值为true表示设置上限
# 参数size: 当capped值为true时, 需要指定此参数, 表示上限⼤⼩,当⽂档达到上限时, 会将之前的数据覆盖, 单位为字节
# 查看集合:
> show collections
# 删除集合:
> db.集合名称.drop()

# 3、数据类型
Object ID: ⽂档ID
String: 字符串, 最常⽤, 必须是有效的UTF-8
Boolean: 存储⼀个布尔值, truefalse
Integer: 整数可以是32位或64位, 这取决于服务器
Double: 存储浮点值
Arrays: 数组或列表, 多个值存储到⼀个键
Object: ⽤于嵌⼊式的⽂档, 即⼀个值为⼀个⽂档
Null: 存储Null值
Timestamp: 时间戳, 表示从1970-1-1到现在的总秒数
Date: 存储当前⽇期或时间的UNIX时间格式

# 创建⽇期语句如下 :参数的格式为YYYY-MM-DD
> new Date('2017-12-20')
# 每个⽂档都有⼀个属性, 为_id, 保证每个⽂档的唯⼀性
# 可以⾃⼰去设置_id插⼊⽂档,如果没有提供, 那么MongoDB为每个⽂档提供了⼀个独特的_id, 类型为objectID
# objectID是⼀个12字节的⼗六进制数:
前4个字节为当前时间戳
接下来3个字节的机器ID
接下来的2个字节中MongoDB的服务进程id
最后3个字节是简单的增量值

数据库的增删改

  • insert、save、update、remove
sh
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
# 插入:insert
# test01会自动创建
> db.test01.insert({'name':'mxx','age':10})
WriteResult({ "nInserted" : 1 })
# _id自动生成,键值name可以不打引号
> db.test01.find()
{ "_id" : ObjectId("5c7cbe034cb2765ea56d825e"), "name" : "mxx", "age" : 10 }

# 更新:save
> db.集合名称.save(document)
# 如果⽂档的_id已经存在则修改, 如果⽂档的_id不存在则添加

# 简单查询
> db.集合名称.find()

# 更新:update
db.集合名称.update(<query> ,<update>,{multi: <boolean>})
参数query:查询条件
参数update:更新操作符
参数multi:可选, 默认是false,表示只更新找到的第⼀条记录, 值为true表示把满⾜条件的⽂档全部更新

db.stu.update({name:'hr'},{name:'mnc'}) 更新一条,其他字段没了
db.stu.update({name:'hr'},{$set:{name:'hys'}}) 更新一条,其他字段还在
db.stu.update({},{$set:{gender:0}},{multi:true}) 更新全部

注意:"multi update only works with $ operators"


# 删除:remove
> db.集合名称.remove(<query>,{justOne: <boolean>})
参数query:可选,删除的⽂档的条件
参数justOne:可选, 如果设为true或1, 则只删除⼀条, 默认false, 表示删除多条

数据高级查询

  • 数据查询、⽐较运算符、逻辑运算符、范围运算符、⽀持正则表达式、limit和skip、⾃定义查询*、投影、排序、统计个数、消除重复
sh
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# 数据查询
⽅法find(): 查询
db.集合名称.find({条件⽂档})
⽅法findOne():查询,只返回第⼀个
db.集合名称.findOne({条件⽂档})
⽅法pretty(): 将结果格式化
db.集合名称.find({条件⽂档}).pretty()


# ⽐较运算符
等于: 默认是等于判断, 没有运算符
⼩于:$lt (less than)
⼩于等于:$lte (less than equal)
⼤于:$gt (greater than)
⼤于等于:$gte
不等于:$ne
> db.stu.find({age:{$gte:18}})


# 逻辑运算符
and:在json中写多个条件即可
查询年龄⼤于或等于18, 并且性别为true的学⽣
db.stu.find({age:{$gte:18},gender:true})

or:使⽤$or, 值为数组, 数组中每个元素为json
查询年龄⼤于18, 或性别为false的学⽣
db.stu.find({$or:[{age:{$gt:18}},{gender:false}]})

查询年龄⼤于18或性别为男⽣, 并且姓名是郭靖
db.stu.find({$or:[{age:{$gte:18}},{gender:true}],name:'gj'})


# 范围运算符
使⽤"$in""$nin" 判断是否在某个范围内
查询年龄为18、 28的学⽣
db.stu.find({age:{$in:[18,28]}})


# ⽀持正则表达式
使⽤//或$regex编写正则表达式
查询姓⻩的学⽣
db.stu.find({name:/^⻩/})
db.stu.find({name:{$regex:'^⻩'}})


# limit和skip
⽅法limit(): ⽤于读取指定数量的⽂档
db.集合名称.find().limit(NUMBER)
查询2条学⽣信息
db.stu.find().limit(2)

⽅法skip(): ⽤于跳过指定数量的⽂档
db.集合名称.find().skip(NUMBER)
db.stu.find().skip(2)

同时使用
db.stu.find().limit(4).skip(5)

db.stu.find().skip(5).limit(4)


# ⾃定义查询*
使⽤$where后⾯写⼀个函数, 返回满⾜条件的数据
查询年龄⼤于30的学⽣
db.stu.find({
$where:function() {
return this.age>30;}
})


# 投影
在查询到的返回结果中, 只选择必要的字段
db.集合名称.find({},{字段名称:1,...})
参数为字段与值, 值为1表示显示, 值为0不显
特殊: 对于_id列默认是显示的, 如果不显示需要明确设置为0

db.stu.find({},{_id:0,name:1,gender:1})


# 排序
⽅法sort(), ⽤于对 集进⾏排序
db.集合名称.find().sort({字段:1,...})
参数1为升序排列
参数-1为降序排列
根据性别降序, 再根据年龄升序
db.stu.find().sort({gender:-1,age:1})


# 统计个数
⽅法count()⽤于统计结果集中⽂档条数
db.集合名称.find({条件}).count()
db.集合名称.count({条件})
db.stu.find({gender:true}).count()
db.stu.count({age:{$gt:20},gender:true})


# 消除重复
⽅法distinct()对数据进⾏去重
db.集合名称.distinct('去重字段',{条件})
# 年龄大于20的学生家乡 去重集合
db.stu.distinct('hometown',{age:{$gt:18}})

数据的备份和恢复

sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
备份的语法:
mongodump -h dbhost -d dbname -o dbdirectory
-h: 服务器地址, 也可以指定端⼝号
-d: 需要备份的数据库名称
-o: 备份的数据存放位置, 此⽬录中存放着备份出来的数据

mongodump -h 192.168.196.128:27017 -d test1 -o ~/Desktop/test1bak

恢复语法:
mongorestore -h dbhost -d dbname --dir dbdirectory
-h: 服务器地址
-d: 需要恢复的数据库实例
--dir: 备份数据所在位置

mongorestore -h 192.168.196.128:27017 -d test2 --dir ~/Desktop/test1bak/test1

聚合和管道

聚合 aggregate

管道:前面的输出是后面的输入

常用管道:

Code
1
2
3
4
5
6
7
8
9
在mongodb中,⽂档处理完毕后, 通过管道进⾏下⼀次处理
常用管道如下:
$group: 将集合中的⽂档分组, 可⽤于统计结果
$match: 过滤数据, 只输出符合条件的⽂档
$project: 修改输⼊⽂档的结构, 如重命名、 增加、 删除字段、 创建计算结果
$sort: 将输⼊⽂档排序后输出
$limit: 限制聚合管道返回的⽂档数
$skip: 跳过指定数量的⽂档, 并返回余下的⽂档
$unwind: 将数组类型的字段进⾏拆分

表达式:

Code
1
2
3
4
5
6
7
8
9
10
处理输⼊⽂档并输出
语法:表达式:'$列名'
常⽤表达式:
$sum: 计算总和, $sum:1 表示以⼀倍计数,计算该文档条数
$avg: 计算平均值
$min: 获取最⼩值
$max: 获取最⼤值
$push: 在结果⽂档中插⼊值到⼀个数组中
$first: 根据资源⽂档的排序获取第⼀个⽂档数据
$last: 根据资源⽂档的排序获取最后⼀个⽂档数据
  • $group、$push、$project、$match
sh
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# $group
将集合中的文档分组,用于统计结果
# _id表示分组依据
例1:统计男生,女生总人数
db.stu.aggregate(
{$group:
{
_id:'$gender',
counter:{$sum:1}
}
}
)
输出:
{"id":false,"count":2}
{"id":true,"count":5}

# Group by null
# 求学生总人数、平均年龄
db.stu.aggregate(
{$group:
{
_id:null,
counter:{$sum:1},
avgAge:{$avg:'$age'}
}
}
)


# $project
# 查询学生年龄、姓名
db.stu.aggregate(
{$project:
{
_id:0,
name:1,
age:1
}
}
)

# 查询男女生人数,输出人数
db.stu.aggregate(
{$group:
{
_id:'$gender',
counter:{$sum:1}
}
},
{$project:{_id:0,counter:1}}
)


# $match
# match是管道命令,能将结果交给后一个管道,但是find不可以
db.stu.aggregate(
{$match:{age:{$gt:20}}},
# 下一个管道....
)


# $push
# 统计不同性别的学生姓名
db.stu.aggregate(
{$group:
{
_id:'$gender',
name:{$push:'$name'}
}
}
)

# $$ROOT:将文档内容加入到结果集的数组中
db.stu.aggregate(
{$group:
{
_id:'$gender',
name:{$push:'$$ROOT'}
}
}
)
  • $sort、$limit、$skip:

  • $unwind
Code
1
2
3
4
5
6
7
8
9
10
11
将⽂档中的某⼀个数组类型字段拆分成多条, 每条包含数组中的⼀个值

语法:db.集合名称.aggregate({$unwind:'$字段名称'})

db.t2.insert({_id:1,item:'t-shirt',size:['S','M','L']})
db.t2.aggregate({$unwind:'$size'})

结果如下:
{ "_id" : 1, "item" : "t-shirt", "size" : "S" }
{ "_id" : 1, "item" : "t-shirt", "size" : "M" }
{ "_id" : 1, "item" : "t-shirt", "size" : "L" }

索引

  • 创建索引
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
索引:以提升查询速度

测试:插入10万条数据到数据库中
for(i=0;i<100000;i++){db.t12.insert({name:'test'+i,age:i})}

db.t1.find({name:'test10000'})
db.t1.find({name:'test10000'}).explain('executionStats')
# 52ms

建立索引之后对比:
语法:db.集合.ensureIndex({属性:1}),1表示升序, -1表示降序
具体操作:db.t1.ensureIndex({name:1})
db.t1.find({name:'test10000'}).explain('executionStats')
# 0ms
  • 关于索引
Code
1
2
3
4
5
6
7
8
9
10
11
在默认情况下创建的索引均不是唯一索引。
创建唯一索引:
db.t1.ensureIndex({"name":1},{"unique":true})
创建唯一索引并消除重复(name是唯一的,爬虫时用于数据去重):
db.t1.ensureIndex({"name":1},{"unique":true,"dropDups":true})  
建立联合索引(什么时候需要联合索引):
db.t1.ensureIndex({name:1,age:1})
查看当前集合的所有索引:
db.t1.getIndexes()
删除索引:
db.t1.dropIndex({'索引名称'}:1)
  • 爬虫数据去重,实现增量式爬虫

与python交互

设置mongodb远程访问

sh
1
2
3
4
5
6
7
8
9
# 关闭防火墙 firewalld\iptables
systemctl stop firewalld.service #停止firewall
systemctl disable firewalld.service #禁止firewall开机启动

# 设置mongodb远程访问
# 编辑mongod.conf注释bindIp,并重启mongodb.(这句配置代表只能本机使用,所以需注释)
vim /etc/mongod.conf

systemctl restart mongod.service

增删改查

python
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
from pymongo import MongoClient

# 建立连接
client = MongoClient(host="10.211.55.6", port=27017)
# 集合

# 插入数据
collection = client["test02"]["t003"]
collection.insert({"name": "mxx", "age": 18})

# 插入多条数据
data_list = [{"name": "test{}".format(i)} for i in range(10)]
collection.insert_many(data_list)

#查询一个记录
# t = collection.find_one({"name":"xiaowang"})
# print(t)
#查询所有记录
t = collection.find({"name":"xiaowang"})
print(t)

# for i in t:
# print(i)
#
# for j in t:
# print(j,"*"*100)
print(list(t))


# 更新
collection.update_one({...})
collection.update_many({...})

# 删除
collection.delete_one({})
collection.delete_many({})


# 不用断开连接,会自动断开
文章作者: Machine
文章链接: https://machine4869.gitee.io/2019/03/04/20190304105434006/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 哑舍
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论