什么是数据库
在网络交互的过程中,不仅会有数据的传递,也会有新数据的产生。比如我们目前的网站登录注册项目,在用户注册后,我们只是把数据添加到了服务器的内存中,但是程序一旦关闭或者重启,内存中的数据就消失了,服务器会恢复到最初的样子,那注册的用户数据也就没有了。这对于网站来讲,是不可接受的。那么如何解决这个问题呢?
服务器程序,就像是我们大脑的记忆,并不是长久的,一旦重启,就会失忆。俗话说,好记性不如烂笔头。因此最好的办法,就是把数据记录并保存下来。
在早期的网站中,通过把数据写入到文件中来进行保存,即便电脑关闭重启,文件也不会消失。但慢慢的又发现了问题,当文件存储内容过多的时候,很难找到我们想要的那条数据,而且,读取文件也是一个非常耗时的过程。
为了能够更好的存储数据,数据库应运而生,在本系列课程中,我们要使用的数据库是MongoDB。
图书馆是一个存储图书的地方,粮仓是用来存储粮食的。数据库,顾名思义,就是专门用来存储数据的仓库。存储在数据库中的数据,能够长期的保存,并且易于查找。
在数据库中,数据不是杂乱无章的,它们会放在一个一个的小盒子里,在MongoDB中这些盒子就称为集合。一个数据库中可以有多个集合,而集合中存储的是一条一条的数据。
MongoDB简介
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。
在现代的计算系统上每天网络上都会产生庞大的数据量。
这些数据有很大一部分是由关系数据库管理系统(RDBMS)来处理。 1970年 E.F.Codd's提出的关系模型的论文 "A relational model of data for large shared data banks",这使得数据建模和应用程序编程更加简单。
通过应用实践证明,关系模型是非常适合于客户服务器编程,远远超出预期的利益,今天它是结构化数据存储在网络和商务应用的主导技术。
NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。
- 易扩展: NoSQL数据库种类繁多, 但是一个共同的特点都是去掉关系数据库的关系型特性。 数据之间无关系, 这样就非常容易扩展
- 大数据量,高性能: NoSQL数据库都具有非常高的读写性能, 尤其在大数据量下表现优秀。 这得益于它的非关系性,数据库的结构简单
- 灵活的数据模型: NoSQL无需事先为要存储的数据建立字段, 随时可以存储自定义的数据格式。 而在关系数据库中, 增删字段是一件非常麻烦的事情。
MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统。
在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为WEB应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
- 安装:sudo apt install -y mongodb
- 默认端口:27017
- 默认配置文件的位置:/etc/mongod.conf
- 默认日志的位置:/var/log/mongodb/mongod.log
- 查看日志:grep -v '#' /etc/mongodb.conf
创建和删除数据库
- 创建/切换数据库:use DATABASE_NAME,如果数据库不存在,则创建数据库,否则切换到指定数据库。没有切换数据库的情况下默认使用test数据库。
- 查看所有数据库:show dbs / show databases
- 删除当前的数据库:db.dropDatabase()
创建和删除集合
- 创建集合:db.createCollection(name,options)db.createCollection('stu', { capped:true, size:200, max:2} )参数capped:默认值为false表示不设置上限,值为true表示设置上限参数size:集合所占用的字节数。 当capped值为true时,需要指定此参数,表示上限大小,当文档达到上限时, 会将之前的数据覆盖,单位为字节参数max:文档最大数量
- 查看集合:show collections
- 删除集合:db.集合名称.drop()
- 检查集合是否设定上限: db.集合名.isCapped()
启动方式:测试启动
- 启动: sudo service mongod start
- 停止: sudo service mongod stop
- 重启: sudo service mongod restart
启动失败:Failed to start mongod.service: Unit mongod.service not found.
- 解决方案
- 创建配置文件:sudo vim /etc/systemd/system/mongodb.service
- [Unit] Descriptinotallow=High-performance, schema-free document-oriented database After=network.target [Service] User=mongodb ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf [Install] WantedBy=multi-user.target
- 启动服务
- sudo systemctl start mongodb
- sudo systemctl status mongodb
- 检测是否启动成功:ps aux | grep mongod
- 永久启动:sudo systemctl enable mongodb
生产环境正式的启动方式
启动: sudo mongod [--auth --dbpath=dbpath --logpath=logpath --append --fork] [-–f logfile ]
- 只以 sudo mongod 命令启动时,默认将数据存放在了 /data/db 目录下,需要手动创建
- --dbpath: 指定数据库的存放路径
- --logpath: 指定日志的存放路径
- --append: 或--logappend 设置日志的写入形式为追加模式
- --fork: 或-fork 开启新的进程运行mongodb服务
- --f: 或-f 配置文件路径(可以将上述配置信息写入文件然后通过该文件中的参数进行加载启动)
- --auth: 以权限认证的方式启动
配置文件启动
sudo mongod -f mogo_start.cfg
mongoDB支持的数据类型
mongoDB文档存储是使用BSON类型,BSON(BSON short for Binary JSON, is a binary-encoded serialization of JSON-like documents)是二进制序列化的形式。类如JSON,同样支持内嵌各种类型。
MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中
下表为MongoDB 常用的几种数据类型:
数据类型 | 描述 |
String | 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。 |
Integer | 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。 |
Boolean | 布尔值。用于存储布尔值(真/假)。 |
Double | 双精度浮点值。用于存储浮点值。 |
Array | 用于将数组或列表或多个值存储为一个键。 |
Timestamp | 时间戳。记录文档修改或添加的具体时间。 |
Object | 用于内嵌文档。 |
Null | 用于创建空值。 |
Date | 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。 |
Object ID | 对象 ID。用于创建文档的 ID。 (每个文档都有) |
ObjectId
ObjectId 类似唯一主键,可以很快的去生成和排序,包含 12 bytes,含义是:
- 前 4 个字节表示创建 unix时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
- 接下来的 3 个字节是机器标识码
- 紧接的两个字节由进程 id 组成 PID
- 最后三个字节是随机数
增删改查
- 插入数据:db.集合名称.insert(document)
- db.stu.insert({name:'xiaoming', gender:true, age:10, class:'2年4班', score:100})
- db.stu.insert([{ name:'xiaomei', gender:false, age:12, class:'2年3班', score:90 },{ name:'xiaohong', gender:false, age:12, class:'2年3班', score:96 },{ name:'Jack', gender:false, age:12, class:'2年2班', score:98 },{ name:'Allen', gender:true, age:12, class:'2年3班', score:90 }])
- 插文档时,如果不指定_id参数,MongoDB会为文档自动分配一个唯一的ObjectId
- mongodb的保存:db.集合名称.save(document)
如果文档的_id已经存在则修改,如果_id不存在则添加
- mongodb的查询
1.db.集合名称.find({条件文档})
2.方法findOne():查询,只返回第一个db.集合名称.findOne({条件文档})
3.方法pretty(): 将结果格式化;不能和findOne()一起使用!db.集合名称.find({条件文档}).pretty()
- 比较运算符
1.等于: 默认是等于判断, 没有运算符
2.小于:$lt (less than)
3.小于等于:$lte (less than equal)
4.大于:$gt (greater than)
5.大于等于:$gte
6.不等于:$ne
- 逻辑运算符
1.and:在json中写多个条件即可
2.or:使用$or, 值为数组, 数组中每个元素为json
3.范围运算符:使用$in, $nin 判断数据是否在某个数组内
- 使用$regex编写正则表达式:db.stu.find({name:{$regex:'^张'}})
- 自定义查询
1.shell 是一个js的执行环境
2.使用$where写一个函数, 返回满足条件的数据
3.db.stu.find({ $where:function() { return this.age + 10>= 18; } })
- skip和limit分页查询:db.stu.find().skip((page-1)*num).limit(x)
- 投影,在查询到的返回结果中, 只选择必要的字段
1.db.集合名称.find({},{字段名称:1,...})
2.参数为字段与值, 值为1表示显示, 值为0不显
3.特别注意:对于_id列默认是显示的, 如果不显示需要明确设置为0对于其他不显示的字段不能设置为0db.stu.find({},{_id:0,name:1,gender:1})
- 排序:db.集合名称.find().sort({字段:1,...})
1.参数1为升序排列
2.参数-1为降序排列
3.db.stu.find().sort({score:-1,age:1})
- 统计个数
1.db.集合名称.estimated_document_count()
2.db.集合名称.count_documents({条件})
- 去重:db.集合名称.distinct(字段,{条件})
- 更新:db.集合名称.update({query}, {update}, {multi: boolean})
1.参数query:查询条件
2.参数update:更新操作符
3.参数multi:可选,默认是false,表示只更新找到的第一条数据,值为true表示把满足条件的数据全部更新multi参数必须和$set一起使用!
- 删除:db.集合名称.remove({query}, {justOne: boolean})
1.参数query:可选,删除的⽂档的条件
2.参数justOne:可选, 如果设为true或1,则只删除一条,默认false,表示删除全部