MongoDB的学习
本文章是基于B站有极限编程所写
链接:https://www.bilibili.com/video/BV1Vh411t7YM?p=24&spm_id_from=pageDriver&vd_source=41ae64e1e6b04d7d6390f545886cfe00
注:视频中使用的MongDB安装是基于Linux,本文中是基于Windows10
NoSQL
1、NoSQL简史
2、什么是NoSQL
3、为什么使用NoSQL
4、RDBMS VS.NoSQL
5、常见的数据库管理系统
数据库排名网站:
数据库排名网站
6、NoSQL数据库四大家族
7、NoSQL优缺点
MongDB
1、MonDB简介
2、MonDB历史
3、MonDB支持语言
4、MonDB与关系型数据库的对比
5、MonDB数据类型
6、MonDB下载与安装
6.1 下载
windows 版本:
官网下载地址:
MonDB官网下载地址
这里我本人下载的是4.4版本
安装过程
注意选择上面的选择,选择安装路径
7、启动MonDB
下载完之后会显示两个文件夹
点击data文件夹,并且建立db文件夹
打开mongdb的bin文件夹,此时因为环境的不同有可能大家会找不到bin目录
此时
打开命令窗口输入services.msc命令
找到mongdb服务
双击即可看到bin目录
打开bin目录对应的文件夹
在文件处输入cmd打开命令窗口
输入 mongod -dbpath E:\mongdb\MongoDB\Server\4.4\data\db
后面显示的是你的安装路径
加载成功如图所示
启动服务 在bin文件加在此输入cmd 并输入mongo(注意之前的cmd不可关掉否则会运行失败)
8、客户端访问
客户端测试
1、下载自带的客户端软件 Compass
下载安装后运行如图所示
推荐使用熟悉的Navicat
新建Mongdb连接
测试是否可以连接的上
测试是否可以新建数据库
Mongdb安装成功
基本命令
9、关闭MonDB
10、环境变量
配置环境变量,可以让mongodb的使用更加方便
添加环境变量
在path中添加路径
完成之后直接win+R mongo
运行成功
MongoDB用户与权限管理
1、常用权限
2、创建管理用户
> db.createUser({user:"zhangkun",pwd:"zhangkun",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
创建管理用户
创建成功:
登录
b979aea474a9c2bb01255957f7c.png)
3、创建普通用户
管理员登录
创建数据库
db.createUser({user:"testuser",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"test"}]})
4、更新用户
5、删除用户
MongoDB数据库操作
Mongdb的集合操作
文档
user1 = {
"name":"zhangsan",
"age":18,
"hobbies":["music","read"],
"addr":{
"country":"China",
"city":"BJ"
}
}
db.user.insert(user1)
不存在时
存在时
user = {
"name":"wangwu",
"age":20,
"hobbies":["music","read"],
"addr":{
"country":"China",
"city":"BJ"
}
}
db.user.update({"name":"lisi"},user)
0表示不显示,1表示显示
添加索引
MongoDb在Spring中的使用
1、新建一个项目
2、导入依赖
3、编写在普通情况下使用MongoDB代码
测试是否可以连接Mongdb数据库
/**
* 无需用户名密码连接MongoDB
*
*/
@Test
public void testInit01(){
try {
//连接Mongdb
MongoClient mongoClient = new MongoClient("127.0.0.1",27017);
//连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("test");
System.out.println("连接Mongodb数据库成功");
//释放资源
if(mongoClient != null){
mongoClient.close();
}
}catch (Exception e){
System.err.println(e.getClass().getName()+":"+e.getMessage());
}
}
需要密码连接数据库
/**需要用户密码连接Mongdb
*
*/
@Test
public void testInit02(){
try {
//连接到MongoDB服务 如果是远程连接可以替换“Localhost”为服务器所在IP地址
//ServerAddress两个参数分别为服务器地址和端口
ServerAddress serverAddress = new ServerAddress("localhost",27017);
List<ServerAddress> addrs = new ArrayList<>();
addrs.add(serverAddress);
//MongoCredential.createScramSha1Credential的三个参数分别是用户名,数据库,密码
MongoCredential credential = MongoCredential.createScramSha1Credential("username","database","password".toCharArray());
List<MongoCredential>credentials = new ArrayList<>();
credentials.add(credential);
//通过连接认证连接到数据库
MongoClient mongoClient = new MongoClient(addrs,credentials);
//连接到数据库
MongoDatabase mongoDatabase = mongoClient.getDatabase("database");
System.out.println("Connect to database successfully");
//释放资源
if (mongoClient!=null){
mongoClient.close();
}
}catch (Exception e){
}
}
定义工具类
package com.chaoxing.util;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;
/**
* @Author :Kun
* 封装Mongodb的工具类
* @Date 2022/7/4 10:30
*/
public class MongoDBUtil {
private static MongoClient mongoClient = null;
private static MongoClientOptions.Builder builde = null;
private static MongoClientOptions myOptions = null;
//服务器IP
private static String HOST = "127.0.0.1";
//端口
private static int PORT = 27017;
//用户名
//密码
//与目标数据库可以建立的连接最大数
private static int CONNECTIONS_PERHOST =100;
//这个参数是跟connectsPerHost配套的,当连接数超过connectsPerHost的时候,需要建立新的连接
//连接请求会被阻塞,这个参数就代表允许阻塞请求的最大值,超过这个值之后的请求都会报错
private static int THREADS_ALLOWED_TO_BLOCK_FOR_CONNECTION_MULTIPLIER= 100;
//与数据库建立连接的超时时间
private static int CONNECT_TIMEOUT = 1000*60*20;
//一个线程成功获取到一个可用数据库之前的最大等待时间
private static int MAX_WAITTIME =100*60*5;
//执行 IO操作的超时时间,默认为0,代表不超时
private static int SOCKE_TIMEOUT = 0;
/**
* 初始化连接池
*/
static {
try {
builde = new MongoClientOptions.Builder();
builde.connectionsPerHost(CONNECTIONS_PERHOST);
builde.threadsAllowedToBlockForConnectionMultiplier(THREADS_ALLOWED_TO_BLOCK_FOR_CONNECTION_MULTIPLIER);
builde.connectTimeout(CONNECT_TIMEOUT);
builde.maxWaitTime(MAX_WAITTIME);
myOptions= builde.build();
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 通过连接池获取连接对象作为服务器
*/
public static MongoClient getMongoClient(){
if(myOptions!=null){
return mongoClient;
}
try {
mongoClient = new MongoClient(new ServerAddress(HOST,PORT),myOptions);
return mongoClient;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
/**
* 释放资源
*/
public static void close(MongoClient mongoClient){
if(mongoClient!=null){
mongoClient.close();
}
}
}
在springBoot中使用Mongodb
1、新建项目
2、导入依赖
<!-- spring data mongodb 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
3、建立实体类
package com.xxxx.pojo;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import java.io.Serializable;
/**
* 把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档
* 可以省略,如果省略,则默认使用类名小写映射集合
* 若未加 @Document ,则 save 到 people
* 若添加 @Document ,则 save 到 collection1
*/
@Document("people")
public class People implements Serializable {
//主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写
@Id
private String id;
//该属性对应mongodb的字段的名字,如果一致,则无需该注解
@Field("name")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private int age;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "People{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
'}';
}
}
4、修改配置文件
spring:
data:
# mongodb配置
mongodb:
# 服务器地址
host: 127.0.0.1
# 端口
port: 27017
# 用户名
username: admin
# 密码
password: 'admin'
# 认证数据库
authentication-database: admin
# 操作的数据库
database: test
没有设置账户密码可以注释
4、Mongodb插入语句
@Test
public void insert() {
People people = new People();
people.setAge(100);
people.setName("张三132");
People result = mongoTemplate.insert(people);
}
5、修改文档
@Test
public void save() {
People people = new People();
people.setId("60cb02154209496eec9a4315");
people.setAge(20);
people.setName("张三");
// id不存在就是保存,存在就是更新
People result = mongoTemplate.save(people);
System.out.println(result);
}
如果对象一样则为修改如果对象不一样则为添加
6、查询修改文档
@Test
public void updateFirst() {
// 设置查询体,查询条件具体内容
Criteria criteria = Criteria.where("name").is("张三");
// query设置查询条件
Query query = new Query(criteria);
// 设置修改哪些属性
Update update = new Update();
update.set("name", "张三123");
// People.class 告诉Spring Data MongoDB 上面的属性是哪个类。
// 类对应集合,就知道具体操作集合的哪个属性
UpdateResult result = mongoTemplate.updateFirst(query, update, People.class);
// 修改数量,如果修改前和修改后相同,返回0
System.out.println(result.getModifiedCount());
// 匹配数量。最多返回1,即使有多个张三返回也是1.
System.out.println(result.getMatchedCount());
}
7、更新多个
@Test
public void updateMulti() {
// 设置查询体,查询条件具体内容
Criteria criteria = Criteria.where("name").is("张三123");
// query设置查询条件
Query query = new Query(criteria);
// 设置修改哪些属性
Update update = new Update();
update.set("age", 18);
// People.class 告诉Spring Data MongoDB 上面的属性是哪个类。
// 类对应集合,就知道具体操作集合的哪个属性
UpdateResult result = mongoTemplate.updateMulti(query, update, People.class);
// 修改数量。返回所有匹配结果中真实被修改数量
System.out.println(result.getModifiedCount());
// 匹配数量
System.out.println(result.getMatchedCount());
}
8删除数据
//删除数据
@Test
public void remove() {
//移除配置操作的collection 如果是通过javabean映射的
//如果在javabean属性上设置了字段名,那么可以在条件上直接使用People自己的属性名
/*Query query = new Query(Criteria.where("username").is("张三123"));
// 第二个参数告诉Spring Data Mongodb ,name属性对应的类类型。
DeleteResult result = mongoTemplate.remove(query, People.class);
System.out.println(result.getDeletedCount());*/
//移除配置操作的collection 如果是通过通过具体的collection名称选择,那么条件必须是对应collection中字段
Query query = new Query(Criteria.where("name").is("张三132"));
// 第二个参数告诉Spring Data Mongodb ,name属性对应的集合。
DeleteResult result = mongoTemplate.remove(query, "people");
System.out.println(result.getDeletedCount());
}
9 查询所有
/**
* select
*/
@Test
public void select() {
List<People> list = mongoTemplate.findAll(People.class);
list.forEach(System.out::println);
}
10 查询第一个
/**
* select
*/
@Test
public void select2() {
// 获取到结果中第一条数据
// new Query() 表示没有条件
People people = mongoTemplate.findOne(new Query(), People.class);
System.out.println(people);
}
整体代码如下:
package com.xxxx;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.xxxx.pojo.People;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.SortOperation;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
/**
* Unit test for simple App.
*/
@SpringBootTest
public class AppTest {
@Resource
private MongoTemplate mongoTemplate;
@Test
public void insert() {
People people = new People();
people.setAge(100);
people.setName("张三132");
People result = mongoTemplate.insert(people);
}
//save
@Test
public void save() {
People people = new People();
people.setId("60cb02154209496eec9a4315");
people.setAge(20);
people.setName("张三");
// id不存在就是保存,存在就是更新
People result = mongoTemplate.save(people);
System.out.println(result);
}
@Test
public void updateFirst() {
// 设置查询体,查询条件具体内容
Criteria criteria = Criteria.where("name").is("张三");
// query设置查询条件
Query query = new Query(criteria);
// 设置修改哪些属性
Update update = new Update();
update.set("name", "张三123");
// People.class 告诉Spring Data MongoDB 上面的属性是哪个类。
// 类对应集合,就知道具体操作集合的哪个属性
UpdateResult result = mongoTemplate.updateFirst(query, update, People.class);
// 修改数量,如果修改前和修改后相同,返回0
System.out.println(result.getModifiedCount());
// 匹配数量。最多返回1,即使有多个张三返回也是1.
System.out.println(result.getMatchedCount());
}
@Test
public void updateMulti() {
// 设置查询体,查询条件具体内容
Criteria criteria = Criteria.where("name").is("张三123");
// query设置查询条件
Query query = new Query(criteria);
// 设置修改哪些属性
Update update = new Update();
update.set("age", 18);
// People.class 告诉Spring Data MongoDB 上面的属性是哪个类。
// 类对应集合,就知道具体操作集合的哪个属性
UpdateResult result = mongoTemplate.updateMulti(query, update, People.class);
// 修改数量。返回所有匹配结果中真实被修改数量
System.out.println(result.getModifiedCount());
// 匹配数量
System.out.println(result.getMatchedCount());
}
//删除数据
@Test
public void remove() {
//移除配置操作的collection 如果是通过javabean映射的
//如果在javabean属性上设置了字段名,那么可以在条件上直接使用People自己的属性名
/*Query query = new Query(Criteria.where("username").is("张三123"));
// 第二个参数告诉Spring Data Mongodb ,name属性对应的类类型。
DeleteResult result = mongoTemplate.remove(query, People.class);
System.out.println(result.getDeletedCount());*/
//移除配置操作的collection 如果是通过通过具体的collection名称选择,那么条件必须是对应collection中字段
Query query = new Query(Criteria.where("name").is("张三132"));
// 第二个参数告诉Spring Data Mongodb ,name属性对应的集合。
DeleteResult result = mongoTemplate.remove(query, "people");
System.out.println(result.getDeletedCount());
}
/**
* select
*/
@Test
public void select() {
List<People> list = mongoTemplate.findAll(People.class);
list.forEach(System.out::println);
}
/**
* select
*/
@Test
public void select2() {
// 获取到结果中第一条数据
// new Query() 表示没有条件
People people = mongoTemplate.findOne(new Query(), People.class);
System.out.println(people);
}
@Test
void find() {
Query query = new Query(Criteria.where("age").gte(18));
List<People> list = mongoTemplate.find(query, People.class);
list.forEach(System.out::println);
}
@Test
void findById() {
People peo = mongoTemplate.findById("60cb02154209496eec9a4315", People.class);
System.out.println(peo);
}
@Test
void exists() {
Query query = new Query(Criteria.where("age").exists(true));
List<People> list = mongoTemplate.find(query, People.class);
list.forEach(System.out::println);
}
@Test
void range() {
Query query = new Query(Criteria.where("age").gte(0).lte(99));
List<People> list = mongoTemplate.find(query, People.class);
list.forEach(System.out::println);
}
@Test
void regex() {
// java中正则不需要有//
Query query = new Query(Criteria.where("name").regex("张"));
List<People> list = mongoTemplate.find(query, People.class);
list.forEach(System.out::println);
}
@Test
void findDistinct() {
/**
* findDistinct:
* 查询条件query
* 根据哪个属性去重复。是POJO的属性名称。返回值为此属性去重后的集合。
* 属性所在实体类。
* 属性的类型,此类型作为结果中List集合的泛型。
*/
List<String> list = mongoTemplate.findDistinct(new Query(), "name", People.class, String.class);
list.forEach(System.out::println);
}
@Test
void and() {
Criteria c = new Criteria();
c.andOperator(Criteria.where("name").is("张三132"), Criteria.where("age").is(100));
Query query = new Query(c);
List<People> list = mongoTemplate.find(query, People.class);
list.forEach(System.out::println);
}
@Test
void or() {
Criteria c = new Criteria();
c.orOperator(Criteria.where("name").is("张三"), Criteria.where("age").is(100));
List<People> list = mongoTemplate.find(new Query(c), People.class);
list.forEach(System.out::println);
}
@Test
void orAnd() {
Criteria and1 = new Criteria();
and1.andOperator(Criteria.where("name").is("张三"), Criteria.where("age").is(12));
Criteria and2 = new Criteria();
and2.andOperator(Criteria.where("name").is("李四"), Criteria.where("age").is(20));
Criteria c = new Criteria();
c.orOperator(and1, and2);
List<People> list = mongoTemplate.find(new Query(c), People.class);
list.forEach(System.out::println);
}
@Test
void sort() {
Query query = new Query(Criteria.where("name").is("张三"));
query.with(Sort.by(Sort.Direction.DESC, "age"));
List<People> list = mongoTemplate.find(query, People.class);
list.forEach(System.out::println);
}
@Test
void page() {
Query query = new Query();
//query.with(PageRequest.of(0,2));
query.with(PageRequest.of(0, 2, Sort.Direction.DESC, "age"));
List<People> list = mongoTemplate.find(query, People.class);
list.forEach(System.out::println);
}
@Test
void aggregate01() {
/**
* Aggregation.group(String ...)设置分组条件,如果没有分组,参数省略。
* count() 取总条数
* as() 给查询出来的总条数起别名
*/
//select count(1) from people
TypedAggregation<People> aggregation = TypedAggregation.newAggregation(People.class,
Aggregation.group().count().as("count"));
//执行聚合命令,第二个参数Map表示返回结果放入到Map中。
AggregationResults<Map> result = mongoTemplate.aggregate(aggregation, Map.class);
// 获取到返回结果。
System.out.println(result.getUniqueMappedResult());
System.out.println(result.getUniqueMappedResult().get("count"));
}
@Test
void aggregate02() {
/**
* group()参数必须是在People类中存在。
* 设置group参数,表示按照哪个属性进行分组
*/
//select count(1) from people group by name
TypedAggregation<People> aggregation = TypedAggregation.newAggregation(People.class,
Aggregation.group("name").count().as("count"));
AggregationResults<Map> result = mongoTemplate.aggregate(aggregation, Map.class);
// 当执行聚合函数返回结果为多行时使用此方法。
List<Map> list = result.getMappedResults();
list.forEach(System.out::println);
}
@Test
void aggregate() {
//Aggregation.match写在group前面表示先过滤条件在分组。写在后面表示先分组在过滤条件
//select count(1) from people where name = "张三" group by name
/*TypedAggregation<People> aggregation = TypedAggregation.newAggregation(People.class,
Aggregation.match(Criteria.where("name").is("张三")),Aggregation.group("name").count().as("count"));
AggregationResults<Map> result = mongoTemplate.aggregate(aggregation, Map.class);
List<Map> list = result.getMappedResults();
list.forEach(System.out::println);*/
//select count(1) from people group by name having _id = "张三"
TypedAggregation<People> aggregation = TypedAggregation.newAggregation(People.class,
Aggregation.group("name").count().as("count"),Aggregation.match(Criteria.where("_id").is("李四")));
AggregationResults<Map> result = mongoTemplate.aggregate(aggregation, Map.class);
List<Map> list = result.getMappedResults();
list.forEach(System.out::println);
}
}