首页 > 技术文章 > Spider-four

hsmwlyl 原文

计算机速度比较: CPU -> 寄存器 -> 缓存L1/L2/L3 -> 内存 -> 硬盘 -> 网卡 -> BIOS


LMAP: Linux + MySQL + Apache + PHP/Python
Windows Server + SQL Server + ASP.net


SQL(MySQL、Oracle、DB2) 应用场景 :

1. 高度要求事务性场景、银行、物流、贸易、金融,需要大量原子性操作(多个操作共存亡)。
2. 需要持久化存储的 "冷数据" (无需经常改动的数据)。
3. 对安全性要求高的数据(SQL已沉淀几十年, 成熟稳定)。
4. 需要通过统一的 SQL语句 处理的场景(非关系型数据库的语法各不相同)。
5. 业务需要明确的多表结构关系的设计和字段的设计(表间关系错综复杂, 需要经验丰富的架构师)。


NoSQL(内存+硬盘) 应用场景 :

1. 拥有灵活的数据结构, 但也需事先设计表结构关系。
2. 需要存储 IO要求高、"热数据" (随时改动的数据) 的场景[NoSQL基于内存,速度高效]。
3. 高度伸缩性,更易扩展,搭建集群。
4. 较适合于互联网时代多变的数据类型存储。

 

MongoDB 数据库

1. 安装方式:

(Ubuntu 16)第一种: sudo apt-get install -y mongodb-org
(Ubuntu 18)第二种: sudo apt install mongodb


2. 开启服务:

开启 MongoDB 服务: sudo mongod
第一次开启前需手动创建 MongoDB数据库 保存数据的目录: sudo mkdir -p /data/db (递归创建目录) sudo chmod /data/db 777 (给定权限)

开启 MongoDB shell客户端服务: mongo


3. MongoDB数据库 常用命令

# 查看当前所在数据库
> db

# 查看所有的数据库
> show dbs

# 切换到指定数据库,若切换到不存在数据库不会报错,也无需额外创建数据库、集合,当写入数据时会自动创建
> use youyuan

# 查看当前数据库下所有集合(类似于SQL的table)
> show collections

# 查看当前数据下 指定集合 的所有数据
> db.beijing_mm.find()

# 删除当前数据库下 指定的集合
> db.beijing_mm.drop()

#删除当前数据库
> db.dropDatabase()


4. MongoDB数据库 增删改查,remove默认删除所有,update默认更新一条

a. MongoDB 增加数据 insert() -- python代码实现见 "mongodb_insert.py"

# 第一种: 直接写入一条文档
> db.stu.insert({ "_id" : 1, "name" : "刘备", "age" : 40, "hometown" : "蜀" })

# 第二种: 先创建一个空的文档,依次添加数据,最后统一写入
> data = {}
> data._id = 2
> data.name = "关羽"
> data.age = 38
> data.hometown = "蜀"
> db.stu.inesrt(data)

 

b. MongoDB 删除数据 remove() -- python代码实现见 "mongodb_remove.py"

1. remove() 默认删除所有符合条件的 文档数据
> db.stu.remove({age : 35})

2. remove() 通过第二个参数 {justOne : true} 来删除第一条符合条件的文档数据
> db.stu.remove({age : 38}, {justOne : true})

3. remove() 通过空的参数,可以删除当前集合下所有文档数据
> db.stu.remove({})
> db.stu.drop() # 删除集合效果相同

4. 在Python中使用: delete_one 和 delete_many

 

c. MongoDB 修改更新数据 update() -- python代码实现见 "mongodb_update.py"
update至少需提供两个参数: 第一个参数, 匹配的条件; 第二个参数表示, 修改的数据; 第三个参数{multi : true} 表示处理所有文档数据(默认只处理第一条文档)

1. update() 默认将匹配的文档数据,全部替换为 第二个参数的文档数据,但是_id 不变
> db.stu.update({name : "刘备"}, {age : 38, hometown : "蜀国"})

2. update() 通过 $set 修饰符,可以 修改/添加 特定的字段
# 只修改 刘备的 age 为40,并新增gender 为 true
> db.stu.update({name : "刘备"}, {$set : {age : 40, gender : true}})

3. 默认update() 只处理第一条文档,通过 {multi : true} 处理所有文档
> db.stu.update({hometown : "蜀"}, {$set : {gender : true}}, {multi : true})

 

d. MongoDB 新增+替换 整条文档数据 save()
根据 _id 判断: 如果 _id 已存在,则替换一条文档数据; 如果 _id 不存在, 则新增文档数据。

# _id 不存,新增一条文档数据
> db.stu.save({_id : 2, "name" : "诸葛亮", age : 32, hometown : "蜀", gender : true})
# _id 存在,替换该文档数据
> db.stu.save({_id : 2, "name" : "诸葛孔明", age : 32, hometown : "蜀", gender : true})

 

e. MongoDB 查询数据 find()

1. 基本查询: 返回所有符合条件的文档数据
> db.stu.find() # 默认返回前20条数据
> db.stu.find({age : 32}).pretty() # 一个字段占据一行的格式输出结果
> db.stu.findOne({age : 32}) # 仅输出一条符合条件的文档数据


2. 比较运算符 : 用来比较数值大小(通用用于比较数字,不建议比较字符串(会比较首字母的ascii值)):

# 默认等于
> db.stu.find({age : 18})
# 大于
> db.stu.find({age : {$gt : 18}})
# 小于
> db.stu.find({age : {$lt : 18}})
# 大于等于
> db.stu.find({age : {$gte : 18}})
# 小于等于
> db.stu.find({age : {$lte : 18}})
# 不等于
> db.stu.find({age : {$ne : 18}})

# 组合使用: 查找age 大于 16 小于等于 40 的文档数据
> db.stu.find({age : {$gt : 16, $lte : 40}})


3. 逻辑运算符 : 用来表示多个条件的 逻辑关系(与 或)
将多个条件 独立,并全部保存在数组中,再通过 与关系$and 或关系$or 修饰

> db.stu.find({age : {$lt : 30}, gender : false}) # 查询年龄小于30 并且 性别女性 的数据

> db.stu.find({$and : [{age : {$lt : 30}}, {gender : false}]}) # 查询年龄小于30 并且 性别女性 的数据

> db.stu.find({$or : [{age : {$lt : 30}}, {gender : false}]}) # 查询年龄小于30 或者 性别女性 的数据

# 1. 找出 age 小雨等于20岁 或 gender 为 false 的文档。 2. 再找出 hometown 为 蒙古
> db.stu.find({$and : [{hometown : "蒙古"}, {$or : [{age : {$lte : 20}}, {gender : false}]} ] })


4. 范围运算符 : 用来判断字段值是否在指定的数据范围内 $in $nin
# 查找 age 值 在 指定数字范围内的文档数据
> db.stu.find({age : {$in : [18, 19, 20, 40]}}) # 查询年龄等于18、19、20、40的数据

# 查找 hometown 值 在 指定数字范围内的文档数据
> db.stu.find({hometown : {$in : ["蒙古", "桃花岛"]}})
# 查找 hometown 值 不在 指定数字范围内的文档数据
> db.stu.find({hometown : {$nin : ["蒙古", "桃花岛"]}})


5. 正则表达式 : 可以通过正则表达式查询结果

# 正则第一种写法: '//' 内包含的是 正则表达式,匹配所有name以 段开头 的文档数据(适合处理中文)
> db.stu.find({name : /^段/})

# 正则第二种写法: {$regex : "正则"} 适合处理英文
> db.stu.find({name : {$regex : "^段"}})
{ "_id" : 8, "name" : "bIgCat", "age" : 18, "hometown" : "汉", "gender" : true }
{ "_id" : 9, "name" : "BigCat", "age" : 18, "hometown" : "汉", "gender" : true }
# 查询 所有name 以 b开头 的文档(且忽略 b 大小写)
> db.stu.find({name : {$regex : "^b", $options : "$i"}})


6. 自定义函数查询 $where : 可以自定义一个 JavaScript函数 执行查询(通常用于补充)
# $where 表示自定义函数执行,会返回集合里的所有符合条件的文档
> db.stu.find({$where : function() {return this.age >= 20}})

# 结果等同于下面语句
> db.stu.find({age : {$gte : 20}})

 

5. MongoDB 处理查询结果

a. limit() & skip() : limit() 是限定个数输出 ; skip() 是跳过个数再输出。 在一起组合使用时,一定是先 skip() 再 limit()

> db.stu.find().limit(3) # 限定只输出三条文档数据
> db.stu.find().skip(3) # 跳过前三个文档数据,输出后面的数据
> db.stu.find().skip(3).limit(4) # 跳过前三个,限定输出后面的4个


b. 投影输出 : 对文档的特定字段进行处理(显示或不显示)。 在 find() 中添加第二个参数,表示启用投影,可以对字段进行投影处理
# 只显示 name 和 age,其他默认不显示
> db.stu.find({}, {name : 1, age : true})
# 不显示 age 和 gender,其他默认显示
> db.stu.find({}, {age : 0, gender : false})
# 不管是 显示还是不显示, _id 是个特殊的字段,默认都会显示(除非手动指定不显示)
> db.stu.find({}, {age : 1, name :true, _id : false})

注: 显示使用 1/true , 不显示使用 0/false,除_id字段之外不能混合使用0-1/true-false


c. 排序 sort() : 对文档的特定字段进行排序处理(1 为升序, -1 为降序)
# 组合排序:先对age进行升序排序,如果有相同 age值,再按 _id进行降序排序
> db.stu.find({"gender" : true}).sort({age : 1, _id : -1})

注意:在Python代码中,sort将做为 find()方法的参数使用,避免和Python的sort冲突
stu.find({"gender" : True}, sort=[("age", 1), ("_id", -1)])


d. 统计个数 count() : 统计所有查询结果的个数,返回一个数字
# 推荐写法
db.stu.find({gender : true}).count()
# 不建议
db.stu.count({gender : true})

 

6. MongoDB 索引,普通索引可提高查询效率,唯一索引可用于去重,索引过多会影响数据库写入速度,所以需要进行读写分离

在MongoDB数据库中增加10000条数据: for(i=0;i<1000000;i++) { db.data.insert({_id : i, name : "name"+i, age : i+1})}

1. 查看当前集合下的所有索引
> db.data.getIndexes()

2. 查看find()执行状态(可以统计执行耗时)
> db.data.find({name : "name9527"}).explain("executionStats")

3. 创建索引
> db.data.ensureIndex({name : 1, age : 1})

4. 创建唯一索引 (根据字段创建的唯一索引,如果后续有相同字段值 则无法写入,可用于去重)
> db.data.ensureIndex({"name" : 1}, {"unique":true})

5. 删除索引
#注意:删除索引根据索引名称删除,可以通过 getIndexes() 查询索引名
> db.data.dropIndex("name_1")

 

7. MongoDB 权限管理

普通模式的MongoDB服务: sudo mongod 这种模式下,任何人都是最高权限
开启权限模式的MongoDB服务: sudo mongod --auth 权限模式下,不同账户指定权限操作数据

1. 开启服务: sudo mongod --auth

2. 创建用户
> use admin
#第一个用户必须是root权限的用户,需要之后通过登录才可以创建其他用户
> db.createUser({uesr : "python", pwd : "123456", roles : ["root"]})

3. 登录到root用户
> use admin
> db.auth("python", "123456")


4. 创建其他用户,并指定权限
> db.createUser({
user : "xiaowang",
pwd : "xiaowang123",
# 对db1 只读权限, db2 有读写权限
roles : [{role : "read", db : "db1"}, {role : "readWrite", db : "db2"}]
})

5. 查看当前MongoDB的所有用户
> use admin
> show users


6. 删除用户(root用户也可以删除自身)
> use admin
> db.dropUser("xiaowang")

 

8、MongoDB数据库的 备份和恢复(以数据库为单位,处理远程数据库)

1. 备份命令 : 提供参数 -h 被备份的主机ip -d 数据库名 -o 备份到本机的指定目录
> sudo mongodump -h 192.168.28.50 -d movie -o ./

2. 恢复命令: 提供参数 -h 被恢复的主机IP -d 数据库名 --dir 指定备份的数据库目录
> sudo mongorestore -h 192.168.28.55 -d movie --dir ./movie


9、MongoDB数据的 导出和导入(以集合为单位,处理本地数据库)

1. 导出命令 : -d 被导出的数据库 -c 被导出的集合名 -o 导出的文件名 (json、csv)
> sudo mongodexport -d test -c stu -o stu.json
> sudo mongodexport -d test -c stu -o stu.csv --type csv -f _id,name,hometown,age,gender

2. 导入命令 : -d 被导入的数据库 -c 被导入的集合名 --file 需要导入的json文件
> sudo mongoimport -d test -c stu --file stu.json


8、9 通常和Linux的 crontab 定时任务合用。

 

推荐阅读