认识MongoDB
NoSQL
NoSQL : Not Only SQL , 非关系型数据库 , 其本质也是一个数据库 , 但相比传统数据库他可以不遵循一些约束 ,比如 : SQL标准 , ACID属性 , 表结构等
特点 :
- 满足对数据库的高并发读写
- 对海量数据的高效存储和访问
- 对数据库扩展性和高可用性
- 灵活的数据结构 , 满足数据库不固定的场景
缺点 :
- 一般不支持事物
- 实现复杂SQL查询比较复杂
- 对运维人员的要求门槛高
- 目前还不算主流的数据库技术
MongoDB简介
什么是MongoDB
MongoDB是一个以Json为数据模型的文档非关系性数据库
什么是非关系性数据库
NoSQL , 一种区分关系性数据库的数据存储方案 , 具有易扩展 , 大数据量 , 高性能 ,灵活数据模型 , 高可用性等特点
为什么叫文档数据库
文档来自"JSON Document" 并不是我们理解的PDF , Word文档
特点 :
- 建模灵活
- json数据模型
- 横向扩展简单
- 大数据量存储
- 高并发
MongoDB的优势
MongoDB才用bson结构存储数据 , 建模方式自然而不是直观
建模灵活可拓展
- 多样性 : 同一个集合(表)异构数据(不同字段的文档对象)
- 动态性 : 需求变更 , 字段可根据需求动态拓展
- 数据治理 : 支持Json Schema规范 ,限制字段类型 , 在保证模型的灵活性前提下 , 保证数据的安全性
- API自然 , 快速开发
- 原生的高可用与易拓展
MongoDB的使用场景
MongoDB的不使用的场景 :
- 对事物要求较高的系统 : 比如 : 银行 , 财务 ,金融类等系统 , MongoDB对事物的支持比较弱
- 传统的对SQL要求比较高的系统 , 特定问题的数据分析 , 多数据实体关联
- 涉及到复杂的 , 高度优化的查询方式
- 较为简单系统 , 数据结构相对固定 , 使用SQL进行查询统计更加便利的时候
MongoDB小结
MongoDB : 是一个非关系性数据库 , 高性能 , 无模式 , 文档性 , 目前NoSQL中最热门的数据库 , 开源产品 , 基于C++开发 , 是NoSql数据库中功能最丰富的 , 最像关系性数据库
特点 :
- 面向集合文档的存储 ,适合存储Bson(json的扩展)形式的数据
- 格式自由 , 数据格式不固定 ,生产环境下修改结构都可以不影响程序运行
- 强大的查询语句 , 面向对象的查询语言 , 基本覆盖SQL语言所有能力
- 完整的索引支持 , 支持查询计划
- 支持复制和自动故障转移
- 支持二进制数据及大型对象(文件)的高效存储
- 使用分片集群提升系统扩展性
- 使用内存映射存储引擎 , 把磁盘的IO操作转换为内存的操作
概括起来就是 :
MongoDB能存 : 海量 , 不敏感 , 有要求一定查询性能的数据
MongoDB安装
服务端
下载地址 : Download MongoDB Community Server | MongoDB
window版安装 :
方式1 :安装版
现在后双击安装 ,然后一路的next ,适合小白
方式2 :绿色版
下载后解压配置
步骤1 : 解压创建2个目录
在解压后的根目录下创建2个目录夹
data/db : 用于存放数据库信息
logs : 存放运行日志
步骤2 : 进入bin目录 , 配置配置文件 : mongo.conf
# 数据库文件路径
dbpath=D:\mongodb-4.2.2\data\db
# 日志文件
logpath=D:\mongodb-4.2.2\logs\mongo.log
# 日志采用追加模式,配置后mongodb日志会追加到现有的日志文件,不会重新创建一个新文件
logappend=true
# 启用日志文件,默认启用
journal=true
# 这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为 false
quiet=true
# 端口号 默认为 27017
port=27017
注意 : 重点修改dbpath跟logpath路径 , 分别指向步骤1中创建的目录
步骤3 : 写一个启动脚本 : statup.bat
mongod --config ./mongo.conf
步骤四 : 双击statup.bat命令启动MongoDB
客户端
MongoDB客户端有非常多的选择
MongoVUE RockMongo Studio 3T compass Navicat for MongoDB MongoDB shell
MongoDB shell
MongoDB服务器自带的客户端 : MongoDB shell
Navicat连接MongoDB
到这 , MongoDB 就算安装成功了
核心概念
对MongoDB 有了大体的了解之后 , 接下来就是MongoDB 的基本操作了 , 操作前希望时刻记得 : MongoDB 是一个数据库 , 那么他不会脱离数据库的几个核心概念 : 数据库 , 表 ,列 , 行
概念
MongoDB 概念解析
不管我们学习什么数据库都应该学习其中的基础概念 , 在MongoDB 中基本的概念就是文档 , 集合 , 数据库 , 下面我们挨个介绍
案例 :
至于怎么定义数据库名 , 集合名 , 字段名 ,跟之前MySQL定义数据库名 , 表名 , 列名遵循的规则一样
数据类型
MongoDB支持的数据类型有很多 , 不需要记忆所有, 关注常用即可
数据类型 | 描述 | 举例 |
null | 表示空值或者未定义的对象 | {"x":null} |
boolean | true/false | {"x":true} |
int | 32位整数 | {"x": NumberInt("3")} |
long | 64位整数 | {"x": NumberLong("3")} |
double | 浮点型 | {"x":3.14, "y":3} |
string | UTF-8字符串 | {"x":"王珊珊"} |
_id | 12字节的唯一id , 自动生成 | {"_id":ObjectId("5e2ab4f48847000059006f73")} |
Regular expression | 正则表达式 ,语法同js的正则对象 | {"x": /foobar/i} |
code | JavaScript代码块 | {"x":function(){....}} |
underfind | 未定义 | {"x":undefined} |
array | 值集合或列表 | {"x":["a","b"]} |
object | 文档中嵌入另外一个文档 | {"x":{"a":1, "b":2}} |
date | 从标准纪元开始的毫秒值 | {"date":ISODate("2018-11-26T00:00:00.000Z")} |
数据库与集合
官方操作文档 : Introduction to MongoDB — MongoDB Manual
MongoDB Shell方式
创建数据库
MongoDB没有专门的创建数据库的命令, 可以使用use 来选择某个数据库, 如果库不存在, 将会创建,但是只有往该库加入文档后才保存成文件
删除数据库
db.dropDatabase(); //删除当前所在的数据库
创建集合
MongoDB中,不用创建集合, 因为没有固定的结构, 直接使用db.集合名称.命令 来操作就可以了, 如果非要显示创建的话使用:
db.createCollection("集合名称")
查看集合
show collections 或者 show tables
删除集合
语法 : db.集合名.drop();
db.users.drop()
Navicat方式
创建数据库
创建集合
注意 : MongoDB的集合最初是没有任何字段的 , 所以默认是一个空 , 里面都没有
文档操作
文档添加
语法 :
db.集合名.insert({文档}) //插入单个
db.集合名.insert([{文档1},{文挡2}]) //插入多个
注意 :
- 往集合中新增文档时 , 当集合不存在的时候 , 会自动先创建集合
- 当操作成功后 , 集合会给文档生成一个_id字段 , 也可以自己指定
文档更新
语法 :
db.集合名.updateOne({query},{update}) //更新单个
db.集合名.updateMany({query},{update}) //更新多个
query : update的查询条件 , 类似于SQL中的update查询内where后面的
update : update的对象和一些更新的操作符(如 : $,$Inc...)等 , 也可以理解为SQL中的update查询内的set后面的
文档删除
语法 :
删除单个 : db.集合名.deleteOne({query})
删除多个 : db.users.deleteMany({query})
文档查询
查询全部 :
db.集合名.find({query},{projection})
query: 是条件 , projection : 列的投影 , 指定返回那些列 , id默返回eg:{"id",0}
排序 :
语法 :
db.集合名.find(query,projection).sort({列:1}) //正序
db.集合名,find(query,projection).sort({列:-1}) //倒序
分页
语法 : db.集合名.find({}).skip(n).limit(m)
条件查询
SQL | MQL |
a = 1 | { a : 1} |
a<>1 | {a :{$ne :1}} |
a > 1 | {a : {$gt : 1}} |
a >= 1 | {a : {$gte : 1}} |
a < 1 | {a : {$lt :1}} |
a <= 1 | {a : {$lte : 1}} |
语法 : db.集合名.find({字段 : {比较运算符 : 值,...}})
比较运算符 | 解释 |
$gt | 大于 |
$gte | 大于等于 |
$lt | 小于 |
$lte | 小于等于 |
$ne | 不等 |
$ln | 在...中 |
逻辑运算
语法 :db.集合名.find({逻辑运算符 : {条件1,条件2, .....}})
比较运算符 | 解释 |
$and | && |
$or | || |
$not | ! |
模糊查询
语法 :
db.集合名,find({列: {$regex" /关键字/ }}) //正则对象
db.集合名.find({列 : {$regex "关键字"}}) // 正则表达式
{name:/xxx/} --->%xxx%
{name:/^xxx/} --->xxx%
{name:/xxx$/} --->%xxx
{name:/xxx/i} 忽略大小写
文档设计
MongoDB文档设计跟普通的关系型数据库表设计类型,但是涉及到关联关系时,需要额外处理。
文档嵌套
一对一关系 , 多对一关系
数组方式
一对多关系 和多对多关系
操作技巧 : 关系型数据库实体对象toJSONString之后就是MongoDB的数据文档
MongoDB编程
SpringBoot集成MongoDB的操作
新建一个项目mongo-demo ,在pom.xml文件中添加依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.3</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!--spring boot data mongodb-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
步骤2:配置mongodb url
# application.properties
# 配置数据库连接
#格式: mongodb://账号:密码@ip:端口/数据库?认证数据库
#spring.data.mongodb.uri=mongodb://root:admin@localhost/mongodemo?authSource=admin
spring.data.mongodb.uri=mongodb://localhost/mongodemo
# 配置MongoTemplate的执行日志
logging.level.org.springframework.data.mongodb.core=debug
步骤3:编写domain实体类
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@ToString
@Document("users") //设置文档所在的集合
public class User {
//文档的id使用ObjectId类型来封装,并且贴上@Id注解,
// 自动映射为_id 自动封装ObjectId
@Id
private String id;
private String name;
private Integer age;
private List<String> hobby = new ArrayList<>();
}
@Id 主键id,将id映射成集合中_id列
步骤4:编写持久层接口
/**
* MongoDB自定义对象的持久层接口
* 1>定义接口继承MongoRepository
* 2>明确指定2个泛型
* 泛型1:当前接口操作实体对象:User
* 泛型2:当前接口操作实体对象对应主键属性类型:id
*/
public interface UserMongoRepository extends MongoRepository<User, String> {
}
步骤5:编写service接口与实现类
public interface IUserService {
void save(User user);
void delete(String id);
void update(User user);
User get(String id);
List<User> list();
}
@Service
public class UserServiceImpl implements IUserService{
@Autowired
private UserRepository userRepository;
@Override
public void save(User user) {
userRepository.save(user);
}
@Override
public void delete(String id) {
userRepository.deleteById(id);
}
@Override
public void update(User user) {
userRepository.save(user);
}
@Override
public User get(String id) {
return userRepository.findById(id).get();
}
@Override
public List<User> list() {
return userRepository.findAll();
}
}
步骤6:CRUD测试
@SpringBootTest
public class UserTest {
@Autowired
private IUserService userService;
@Test
public void testSave(){
User user = new User();
user.setName("王珊珊");
user.setAge(18);
userService.save(user);
}
@Test
public void testUpdate(){
User user = new User();
user.setId("5de507fca0852c6c7ebc1eac");
user.setName("wss2222");
user.setAge(18);
userService.update(user);
}
@Test
public void testDelete(){
userService.delete("5de507fca0852c6c7ebc1eac");
}
@Test
public void testGet(){
System.out.println(userService.get("5de507fca0852c6c7ebc1eac"));
}
@Test
public void testList(){
System.out.println(userService.list());
}
}
基本查询
需求:查询name=王珊珊的数据
步骤1:创建QueryTest
@SpringBootTest
public class QueryTest {
//需求:查询name = dafei用户信息
//MQL: db.users.find({name:"王珊珊"})
@Autowired
private UserRepository repository;
@Test
public void testQuery(){
User user = repository.findByName("王珊珊");
System.err.println(user);
}
}
步骤2:修改UserRepository接口
public interface UserRepository extends MongoRepository<User, String> {
//通过name查询员工数据
User findByName(String name);
}
方案2:MongoTemplate方式
JPA查询语法针对简单条件查询还是可行,但是,如果涉及到高级查询(多条件查询)就无能为力, 怎么办呢?
使用spring-data-mongodb 另外一套操作api---MongoTemplate
需求:查询name=王珊珊的数据
@SpringBootTest
public class QueryTest {
@Autowired
private MongoTemplate template;
@Test
public void testQuery2(){
//类似: mybatyis-plus 条件构造器--Wrapper
Criteria criteria = Criteria.where("name").is("dafei");
// 创建查询对象----MQL语句抽象对象
Query query = new Query();
// 添加限制条件
query.addCriteria(criteria);
List<User> list = template.find(query, User.class, "users");
list.forEach(System.err::println);
}
}
分页查询
@Autowired
private MongoTemplate mongoTemplate;
// 分页查询文档,显示第2页,每页显示3个,按照id升序排列
@Test
public void testQuery1() throws Exception {
// 创建查询对象
Query query = new Query();
// 设置分页信息
query.skip(3).limit(3);
// 设置排序规则
query.with(Sort.by(Sort.Direction.ASC,"id"));
List<User> list = mongoTemplate.find(query, User.class, "users");
list.forEach(System.err::println);
}
到这 , 整个MongoDB只是介绍完了 , 有什么做的不对的 , 欢迎大家私信我