数据库
概述
数据库,为 Database,简称 DB。是按照数据结构组织来存储和管理数据的仓库。
注:这里所说的数据不仅仅包括普通意义的数字,还包括文字、图象、声音等。也就是说,凡是在计算机中用来描述事物的记录都可以称作数据。
特点
- 数据结构化:具有结构,按照结构排列
- 数据共享性,冗余度低且易扩充:数据面向整个系统,并发的共享,减少数据冗余,节约存储空间,同时还能够避免数据之间的不相容性与不一致性。
- 数据独立性:数据的物理独立性和数据的逻辑独立性,数据库管理系统的模式结构和二级映像功能保证
- 数据由DBMS统一管理和控制:数据的统一控制包含安全控制、完整控制和并发控制。简单来说,就是防止数据丢失,确保数据的正确有效,并且在同一时间,允许用户对数据进行多路存取。
分类
根据存储结构划分:非关系型数据库和 关系型数据库
关系型数据库
一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。
关系型数据库的优点:
- 容易理解:二维表结构是非常贴近逻辑世界的一个概念,关系模型相对网状、层次等其他模型来说更容易理解;
- 使用方便:通用的 SQL 语言使得操作关系型数据库非常方便;
- 易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率
关系型数据库的缺点:
- 读写性能比较差,尤其是海量数据的高效率读写;
- 固定的表结构,灵活度稍欠;
- 高并发读写需求,传统关系型数据库来说,硬盘 I/O 是一个很大的瓶颈。
常见的关系型数据库
mysql
Oracle
sqserver
非关系型数据库
非关系型数据库(nosql
)严格上不是一种数据库,而是一种数据结构化存储方法的集合,可以是文档或者键值对(即对象)等。
非关系型数据库优点:
- 格式灵活:存储数据的格式可以是 key-value 形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
- 速度快:
nosql
可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘; - 高并发:支持海量的数据操作
- 成本低:
nosql
数据库部署简单,基本都是开源软件,免费。
非关系型数据库缺点:
- 不提供
sql
支持,学习和使用成本较高; - 无事务处理;
- 数据结构相对复杂,复杂查询方面稍欠。
- 不提供
常见的非关系数据库
MongoDB
:数据库。H2
access
redis
MongoDB
简介
MongoDB
是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是NoSQL
数据库产品中的一种。是最 像关系型数据库(MySQL
)的非关系型数据库。 它支持的数据结构非常松散,是一种类似于JSON
的 格式叫BSON
,所以它既可以存储比较复杂的数据类型,又相当的灵活。
MongoDB
中的记录是一个文档,它是一个由字段和值对(field:value
)组成的数据结构。MongoDB
文档类似于JSON
对象,即一个文档认 为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组。
核心概念
- 数据库:一个数据库可以包含多个集合。
- 集合(
collection
)- 类似于关系性数据库中的表。一个集合中可以包含多个文档.
- 文档(
document
)- 每个文档在程序中都是一个对象来存在
在
MongoDB
中,每一个文档会自动有一个唯一的_id
属性,值是MongoDB
由12个字节自动生成,表示文档唯一。
特点
- 高性能: MongoDB提供高性能的数据持久性。特别是, 对嵌入式数据模型的支持减少了数据库系统上的I/O活动。 索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。
- 高可用性: MongoDB的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余。
- 高扩展性: MongoDB提供了水平可扩展性作为其核心功能的一部分。 分片将数据分布在一组集群的机器上。(海量数据存储,服务能力水平扩展)
- 丰富的查询支持: MongoDB支持丰富的查询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等。
- 其他特点:如无模式(动态模式)、灵活的文档模型、
Mongoose
mongoose是nodejs可扩展的npm包,主要负责nodejs和MongoDB之间的 交互工具。即使用mongoose提供的一系列的api完成数据库在程序中的使用
使用步骤(在express中)
- 全局安装
mongoose
包 - 在app.js中通过api实现连接数据库
- 实现和某个集合的连接
- 针对要使用的集合生成nodejs对应的专属的数据模型(schema)
- 让该模型和集合进行关联
- 创建schema后通过其api实现对该集合数据的crud(增删查改)
连接到数据库
const mongoose = require('mongoose');
const dbURI = 'mongodb://localhost:27017/test'; // 其中 test 为连接的数据库名称
mongoose.connect(dbURI, {useNewUrlParser: true, useUnifiedTopology: true});
mongoose.connection.on('connected', function() {
console.log('Mongoose connected to ' + dbURI);
});
针对集合创建数据模型schema
const studentsSchema = new mongoose.Schema({
文档的属性名: 数据类型,
name: String,
age: Number,
sex:String
});
模型和集合关联
mongoose.model('studentsModel', studentsSchema, 'students');
数据操作(增删查改)
查找数据
语法: mongoose.model("集合模型变量名").find(条件); 1. 查找所有 mongoose.model("集合模型变量名").find(); 2.待条件查找:查找name属性为张三并且age为23 mongoose.model("集合模型变量名").find({name:"张三",age:23}); 3.多选1:查找name为张三或age为23或sex为女 mongoose.model("集合模型变量名").find({ $or: [ {name: '张三'}, {age:{$gt:23}},//大于23 {sex: '男'} ] }); 4. 查找name包含三的数据 mongoose.model("集合模型变量名").find({ name:{$regex:"三",$options:"$i"} });
读取数据库是一个异步操作
添加数据
语法: mongoose.model("集合模型变量名").create(对象); let result = await mongoose.model('studentsModel').create({ name: '赵六', age: 34, sex: '男' }); //result为返回被新增的对象
修改数据
mongoose.model("集合模型变量名").updateOne(条件对象,新对象); mongoose.model("集合模型变量名").updateMany(条件对象,新对象); 例子: let result = await mongoose.model("studentsModel").updateOne({name:'王五'},{name:'王六',sex:'女'}); let result = await mongoose.model("studentsModel").updateMany({age:34},{age:43}); console.log(result);
返回一个对象:包含找到的数据数量以及实际更新的数量
删除数据
语法: mongoose.model("集合模型变量名").deleteOne(条件对象); 语法: mongoose.model("集合模型变量名").deleteMany(条件对象); 例子: let result = await mongoose.model("studentsModel").deleteOne({ sex: '女' }); console.log(result.deletedCount);
多个集合关联操作
- 确保数据库中几个集合之间有关联的属性唯一值,一般是
_id
属性,是集合a保存集合b的_id- 修改这几个集合在mongoose的数据模型
- 在调用api进行数据交互时,如果要完成多集合关联查询时,使用
polulate()
来完成多集合关联操作- 在数据库中,给需要关联的集合的文档添加一个属性,值来自于所关联集合的
_id
的值
修改关联集合的数据模型,添加关联model
1. student集合关联 class集合
const studentsSchema = new mongoose.Schema({
name: String,
age: Number,
sex: String,
//关联部分
classId: {
type: mongoose.SchemaTypes.ObjectId,
//关联集合的数据模型
ref:'classModel'
}
});
populate的使用
集合A 关联集合B(集合A中存在集合B的唯一_id或其他关联属性)
let result = await mongoose.model('集合a的模型名').find().populate('关联集合B的属性');
集合A 关联集合B,集合B关联集合C
let result = await mongoose.model('集合a的模型名').find().populate({ path:"集合A关联集合B的属性", populate:{ path:"集合B关联集合C的属性" } });
集合A关联集合B,集合A关联集合C
let result = await mongoose.model('集合a的模型名').find().populate('集合A关联集合B的属性').populate("集合A关联集合C的属性");