MongoDB

MongoDB

NoSQL

NoSQL:Not Only SQL ,其本质还是一种数据库技术,但相比传统数据库它可以不会遵循一些约束,比如:sql标准、ACID属性,表结构等。

特点

  • 满足对数据库的高并发读写
  • 对海量数据的高效存储和访问
  • 对数据库高扩展性和高可用性
  • 灵活的数据结构,满足数据结构不固定的场景

缺点

  • 一般不支持事务
  • 实现复杂SQL查询比较复杂
  • 运维人员数据维护门槛较高
  • 目前不是主流的数据库技术

具体分类

在这里插入图片描述

为什么是MongoDB

权威数据库排行:https://db-engines.com/en/ranking

在这里插入图片描述

在这里插入图片描述

为啥是MongoDB?答:流行

MongoDB简介

在这里插入图片描述

在这里插入图片描述

MongoDB优势

建模简单而直观

标准的关系型数据库

在这里插入图片描述
*

MongoDB数据库

在这里插入图片描述
*

采用bson结构存储, 建模方式自然而不失直观

建模灵活可拓展

1:多样性:同一个集合(表)异构数据(不同字段的文档对象)

在这里插入图片描述
*

2:动态性:需求变更,字段可更加需求动态拓展

在这里插入图片描述
*

3:数据治理:支持Json Schema规范,限制字段类型,在保证模型的灵活性前提下,保证数据安全

在这里插入图片描述
*

API自然,快速开发

在这里插入图片描述

原生的高可用与易扩展

在这里插入图片描述

MongoDB适用场景

要不要选MongoDB

虽说mongodb很好用,并不是一定要选,开发中需要综合考量(包括学习、开发、运维等成本)

应用特征Yes / No
应用不需要事务及复杂 join 支持必须 Yes
新应用,需求会变,数据模型无法确定,想快速迭代开发
应用需要2000-3000以上的读写QPS(更高也可以)
应用需要TB甚至 PB 级别数据存储?
应用发展迅速,需要能快速水平扩展?
应用要求存储的数据不丢失?
应用需要99.999%高可用?
应用需要大量的地理位置查询、文本查询

如果上述有1个 Yes,可以考虑 MongoDB,2个及以上的 Yes,选择MongoDB绝不会错

MongoDB使用场景

MongoDB 的应用已经渗透到各个领域,比如游戏、物流、电商、内容管理、社交、物联网、视频直播等,以下是几个实际的应用案例

  • 游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
  • 物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
  • 社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
  • 物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
  • 视频直播,使用 MongoDB 存储用户信息、礼物信息等.

MongoDB不使用的场景

  • 对事务要求较高的系统:例如银行、财务、金融类等系统。MongoDB对事物的支持较弱;
  • 传统的对SQL要求较高的系统:特定问题的数据分析,多数据实体关联,
  • 涉及到复杂的、高度优化的查询方式;
  • 较为简单系统;数据结构相对固定,使用sql进行查询统计更加便利的时候;

MongoDB小结

MongoDB:是一个数据库 ,高性能、无模式、文档性,目前nosql中最热门的数据库,开源产品,基于c++开发。是nosql数据库中功能最丰富,最像关系数据库的。

特点:

  • 面向集合文档的存储:适合存储Bson(json的扩展)形式的数据;
  • 格式自由,数据格式不固定,生产环境下修改结构都可以不影响程序运行;
  • 强大的查询语句,面向对象的查询语言,基本覆盖sql语言所有能力;
  • 完整的索引支持,支持查询计划;
  • 支持复制和自动故障转移;
  • 支持二进制数据及大型对象(文件)的高效存储;
  • 使用分片集群提升系统扩展性;
  • 使用内存映射存储引擎,把磁盘的IO操作转换成为内存的操作;

概括起来:

MongoDB能存:海量,不敏感,又要求一定查询性能的数据

MongoDB安装

服务端

下载:https://www.mongodb.com/download-center/community

说明:Linux版的安装,这里不展开讲,后续讲Linux操作系统时再讲,此处重点讲Window版的安装

Window安装版有2种方式:

方式1:安装版

下载后双击安装,然后一路next,next即可,小白首选。
在这里插入图片描述
*

方式2:绿色版

下载后解压配置

步骤1:解压创建2个目录

在解压后的根目录下创建2个目录夹

data/db:用于存放数据库信息

logs:存放运行日志
在这里插入图片描述
*

步骤2:进入bin目录,配置配置文件:mongo.conf

# 数据库文件路径
dbpath=D:\OpenSource\mongodb-4.2.2\data\db
# 日志文件
logpath=D:\OpenSource\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

步骤4:双击启动statup.bat命令

在这里插入图片描述
*

客户端

MongoDB客户端有非常多选择:

MongoVUE RockMongo Studio 3T compass Navicat for MongoDB MongoDB shell

MongoDB Shell

MongoDB服务器自带客户端: MongoDB Shell
在这里插入图片描述
*

在这里插入图片描述

compass

官方推荐:compass

下载:https://www.mongodb.com/products/compass

个人感觉不是很好用,反而Navicat for MongoDB这个相对好用,所以此处选择Navicat for MongoDB作为客户端

Navicat for MongoDB

下载:http://www.navicat.com.cn/products

在这里插入图片描述

Navicat目前企业版(可试用14天)最新是16,MongoDB支持至少12版本,大家根据自己的需要选择。最后强调:支持正版

后续我们使用Navicat Premium 12版本,如果之前有安装过12 或者 12以上可以不用重新安装。

安装步骤:略:无脑next,next,next。

安装成功之后打开:

在这里插入图片描述

在这里插入图片描述
*

创建连接成功之后,默认是看不了数据库的,需要点击查看:显式隐藏项目,才能看到MongoDB系统自带的数据库。

在这里插入图片描述

到这,MongoDB安装算成功啦。

核心概念

对MongoDB有了大体了解之后,接下来就是MongoDB基本操作了。操作前希望时刻记得:MongoDB是一个数据库,那么它不会脱离数据库的几个核心概念:数据库,表,列,行。

概念

在这里插入图片描述

案例

在这里插入图片描述
*

至于怎么定义数据库名, 集合名,字段名,跟之前MySQL定义数据库名,表名,列名遵循的规则一样

数据类型

MongoDB支持的数据类型有很多,不需要记忆所有,关注常用的即可

数据类型描述举例
null表示空值或者未定义的对象{“x”: null}
booleantrue/false{“x”: true}
int32位整数{“x”: NumberInt(“3”)}
long64位整数{“x”: NumberLong(“3”)}
double浮点数{“x”:3.14, “y”:3}
stringUTF-8字符串{“x”:“dafei”}
_id12字节的唯一id,自动生成{“_id”:ObjectId(“5e2ab4f48847000059006f73”)}
date从标准纪元开始的毫秒数{“date”:ISODate(“2018-11-26T00:00:00.000Z”)}
Regular expression正则表达式,语法同js的正则对象{“x”: /foobar/i}
codeJavaScript代码块{“x”:function(){…}}
undefined未定义{“x”:undefined}
array值集合或者列表{“x”:[“a”,“b”]}
object文档中嵌入另外一个文档{“x”:{“a”:1, “b”:2}}

数据库与集合

官网操作文档:https://docs.mongodb.com/manual/introduction/

MongoDB Shell方式

创建数据库

在这里插入图片描述
*

MongoDB没有专门的创建数据库的命令, 可以使用use 来选择某个数据库, 如果库不存在, 将会创建,但是只有往该库加入文档后才保存成文件

在这里插入图片描述
*

删除数据库

db.dropDatabase(); //删除当前所在数据库

创建集合

MongoDB中,不用创建集合, 因为没有固定的结构, 直接使用db.集合名称.命令 来操作就可以了, 如果非要显示创建的话使用:

db.createCollection(“集合名称”)

在这里插入图片描述
*

查看集合

show collections 或者 show tables

在这里插入图片描述
*

删除集合

语法:db.集合名.drop();

db.users.drop()

在这里插入图片描述
*

Navicat方式

创建数据库

在这里插入图片描述

创建集合

在这里插入图片描述

这里注意,MongoDB的集合最初没有任何字段,所以默认是一个空,里面都没有。

文档操作

为了开发方便, 建议使用Navicat的方式操作MongoDB命令。另外学习时,建议新建并保存一个查询文件,方便后续复习。

在这里插入图片描述

题外话: MongoDB 语法使用JavaScript引擎进行解析的,如果你js学得还可以,那你就掌握了先手优势啦。

把港股创建的查询文件保存到桌面,结果是js后缀。

在这里插入图片描述
*

文档添加

语法

db.集合名.insert( {文档} )   		  //插入单个
db.集合名.insert( [{文档1},{文档2}] )   //插入多个

注意

1:往集合中新增文档,当集合不存在时会自动先创建集合

2:当操作成功时,集合会给文档生成一个**_id**字段,也可以自己指定

练习

//添加一个用户: 用户(id:1, name:"dafei", age:18)
db.users.insert({id: 1, name: "dafei", age: 18})

//添加多个用户:用户(id:2, name:"xiaofei", age:16)  用户(id:3, name:"laofei", age:88)
db.users.insert([{id:2, name:"xiaofei", age:16}, {id:3, name:"laofei", age:88}])

查看

在这里插入图片描述
*

换种风格

分别为:网格视图, 树视图,JSON视图

在这里插入图片描述
*

文档更新

语法

//update users set xx=1 where xx = 1
//更新单个
db.集合名.updateOne(
    {query},
    {update}
)

//更新多个
db.集合名.updateMany(
    {query},
    {update}
)

query : update的查询条件,类似sql update查询内where后面的。
update : update的对象和一些更新的操作符(如 , , ,inc…)等,也可以理解为sql update查询内set后面的

练习

//把一个带有name=dafei的文档,修改其age值为30
db.users.updateOne({name: "dafei"}, {$set: {age: 30}})

//修改所有name=dafei的文档,修改其name=大飞,age=20
db.users.updateMany({name: "dafei"}{$set: {name: "大飞", age: 20}})

//修改所有的文档,修改其name=xxx,age=10
db.users.updateMany({}{$set: {name: "xxx", age: 10}})

文档删除

语法

//删除1个:
db.集合名.deleteOne(
   {query}
)
//删除多个:
db.集合名.deleteMany(
   {query}
)

练习

//删除_id=xxx的文档
db.users.deleteOne({_id: ObjectId("xxx")})

//删除所有带有name=dafei的文档
db.users.deleteMany({name: "bunny"})

//删除当前数据库中所有文档
db.users.deleteMany({})

文档查询

数据准备

db.users.insert({"id":NumberLong(1),"name":"dafei","age":NumberInt(18)})
db.users.insert({"id":NumberLong(2),"name":"xiaofei","age":NumberInt(20)})
db.users.insert({"id":NumberLong(3),"name":"zhang quan dan","age":NumberInt(33)})
db.users.insert({"id":NumberLong(4),"name":"zhang kun","age":NumberInt(26)})
db.users.insert({"id":NumberLong(5),"name":"zhang han yun","age":NumberInt(29)})
db.users.insert({"id":NumberLong(6),"name":"cai xv kun","age":NumberInt(29)})
db.users.insert({"id":NumberLong(7),"name":"jia nai liang","age":NumberInt(25)})
db.users.insert({"id":NumberLong(8),"name":"fu rong wang","age":NumberInt(28)})
db.users.insert({"id":NumberLong(9),"name":"wang da","age":NumberInt(31)})
db.users.insert({"id":NumberLong(10),"name":"da wang","age":NumberInt(32)})
db.users.insert({"id":NumberLong(11),"name":"will","age":NumberInt(26)})

查询全部

语法
//sql: select age, name  from table where ....
db.集合名.find({query}{projection})

query: 是条件
projection: 列的投影,指定返回哪些列 _id默认返回 eg: {“_id”: 0}

练习
查所有用户
//sql: select * from users;
db.users.find()
db.users.find({})   //{} 是条件
db.users.find({}, {name:1})  //第二个{} 表示查询哪些列

排序

语法
db.集合名.find(query, projection).
sort(  {列:1}    )      //正序
sort(  {列:-1}   )     //倒序

多列排序
sort(  {1:1, 列2:1}  )
练习
//查询所有用户按年龄排序
//sql: select * from users order by age desc|asc
db.users.find({}).sort({age:1})  //正序
db.users.find({}).sort({age:-1})  //倒序
db.users.find({}).sort({age:-1, id:1})  //多列排序

分页

语法
db.集合名.find({}).skip(n).limit(m)

跟mysql中 limit ? ? 一一对应

练习
//分页查询所有用户
//约定每页显示3条
//sql: select * from users limit 0, 3   
db.users.find().skip(0).limit(3)    //第一页
db.users.find().skip(3).limit(3)    //第二页
...
db.users.find().skip((currentPage-1) * pageSize).limit(pageSize)//第n页

条件查询

比较运算符

在这里插入图片描述
*

语法
db.集合名. find(     {    字段: {比较操作符: 值, ...}      }       )
比较操作符解释
$gt大于
$lt小于
$gte大于等于
$lte小于等于
$ne不等
$in在…中
练习
查询age > 30的用户
//sql: select * from users where age > 300
db.users.find(
  {age: { $gt:30}}
) 


查询名字为 dafei 或xiaofei用户
//sql: select * form users where name in("dafei", "xiaofei")
db.users.find(
  {name: {$in: ["dafei", "xiaofei"]}}
)

逻辑运算符【拓展】

在这里插入图片描述
*

语法
db.集合.find(   {逻辑操作符: [条件1, 条件2...]}   )
比较操作符解释
$and&&
$or||
$not
练习
//查年龄在28 到 30间的用户信息
//sql:  select * from users where age >= 28 and age <=30

db.users.find(
   {age:{$gte:28, $lte:30}}
)

db.users.find(
   {
	    $and:[{age:{$gte:28}},{age:{$lte:30}}]
	 }
)


//查看年龄小于28或者年龄大于30用户信息
//sql: select * from users where age <28 or age >30
db.users.find(
   {$or: [{age: {$lt: 28}}, {age: {$gt:30}}]}
)

//查看年龄等于28或者等于30用户信息
//sql: select * from users where age =28 or age =30
db.users.find(
   {$or: [{age:28}, {age: 30}]}
)

模糊查询【拓展】

语法
db.集合.find({: {$regex: /关键字/}})  //正则对象
db.集合.find({: {$regex: "关键字"}})  //正则表达式

{name:/xxx/}     --->%xxx%
{name:/^xxx/} --->xxx%
{name:/xxx$/} --->%xxx
{name:/xxx/i}   忽略大小写
练习
//查询name带有fei的用户信息
//sql: select * from users where name like '%fei%'
db.users.find(
  {name: {$regex:/fei/ }}
)

//查name中包含fei字样,并且年龄在28 到 30间的用户信息,
//sql:  select * from users where name like '%fei%' and age >= 28 and age <=30
db.users.find(
   {$and: [{name: {$regex:/fei/}}, {age: {$gte:28, $lte:30}}]}
)

文档设计

MongoDB文档设计跟普通的关系型数据库表设计类型,但是涉及到关联关系时,需要额外处理。

文档嵌套

一对一关系 与 多对一关系

在这里插入图片描述
*

数组方式

一对多关系与多对多关系

在这里插入图片描述

操作技巧:关系型数据库实体对象toJsonString之后就是MongoDB的数据文档

MongoDB 编程

这里重点讲解,springboot集成MongoDB的操作

基本CRUD

需求:完成员工的CRUD

步骤1:建立项目mongo-demo

步骤2:导入依赖

<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>

步骤3:配置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("dafei");
        user.setAge(18);
        userService.save(user);
    }

    @Test
    public void testUpdate(){
        User user = new User();
        user.setId("5de507fca0852c6c7ebc1eac");
        user.setName("dafei2222");
        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=dafei数据

方案1:JPA 方式

步骤1:创建QueryTest

@SpringBootTest
public class QueryTest {

    //需求:查询name = dafei用户信息
    //MQL: db.users.find({name:"dafei"})

    @Autowired
    private UserRepository repository;
   
    @Test
    public void testQuery(){
        User user = repository.findByName("dafei");
        System.err.println(user);
    }
}

步骤2:修改UserRepository接口

public interface UserRepository extends MongoRepository<User, String> {
    //通过name查询员工数据
    User findByName(String name);
}

解析:

 /**
 *  Spring-Data-mongodb 实现了JPA 语法规则,所有可以使用JPA查询方法定义规则来实现快速查询
 *
 *    JPA查询方法定义规则:
 *      前缀  + 操作符 + 属性/列
 *
 *      前缀: find  / query
 *      操作符: by and or lessthan like....
 *
 */

在这里插入图片描述

方案2:MongoTemplate方式

JPA查询语法针对简单条件查询还是可行,但是,如果涉及到高级查询(多条件查询)就无能为力, 怎么办呢?

使用spring-data-mongodb 另外一套操作api—MongoTemplate

需求:查询name=dafei数据

@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);
}

  • 8
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值