0.序章
致命的面试问题:为什么使用MongoDB?
大型的分布式的文档型数据库,也是NoSQL数据库(例如 redis)
MongoDB适合数据量大而价值又低的这种数据(播放进度、评论、弹幕,实时数据的CRUD)
因为数据量大,所以不适合用redis,因为redis内存没这么大;
因为价值低,量又大,所以不适合存储在MySQL中;
1.MongoDB的相关概念
常识性的内容(类比MySQL学习):
MongoDB: MySQL:
database 数据库 database数据库
collection 集合(建议结构一样) table表(数据结构必须相同)
Document文档(json BSON Binarry-Json) row行
field字段 column列
_id 主键 id主键
一个数据库可以有多个集合,一个集合可以保存多条Document。
2.安装过程(在docker环境中):
mkdir -p /opt/mongo/data/db
docker load < /opt/mongo.tar
docker run -d --restart=always -p 27017:27017 --name mongodb -v /opt/mongo/data/db:/data/db mongo:8.0-rc
3.命令行
数据库(database)
# 查看数据库
show dbs
# 切换或者新增库(懒加载,当数据库中有集合或者数据时,才会真实创建)
use {dbName}
# 删除库
db.dropDatabase()
集合(collection)
# 创建集合(不是必须操作,操作数据时如果集合不存在则自动创建)
db.createCollection("colName")
# 查看集合
show collections
# 删除集合
db.{colName}.drop()
文档(Document)
# 新增 insert(过期) save(移除) insertOne insertMany
db.{colName}.insertOne({k1:v1,k2:v2})
db.{colName}.insertMany([{k1:v1,k2:v2}, {k1:v1,k2:v2}, {k1:v1,k2:v2}])
# 查询所有
db.{colName}.find()
# 基本查询:等值
db.{colName}.find({k: v, k: v})
# 不等值查询:like($regex) >($gt) <($lt) >=($gte) <=($lte) !=(ne)
db.{colname}.find({k: {$regex: v}})
db.{colName}.find({k: /v/})
# or查询:或者关系
db.{colName}.find({$or: [{k: v}, {k: v}]})
# 排序
db.{colName}.find().sort({key: 1/-1})
# 分页
db.{colName}.find().skip((pageNum-1))*pageSize).limit(pageSize)
# 更新
db.{colName}.updateOne({查询条件}, {$set: {k: v, k: v}})
# 删除
db.{colName}.deleteOne({k: v})
db.{colName}.deleteMany({k: v})
db.{colName}.deleteMany({})
4.Java客户端
UI客户端
官方提供的GUI客户端:MongoDB Compass
Java客户端
SpringData-MongoDB
引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
配置:
# mongodb的配置
spring.data.mongodb.uri=mongodb://ip:port/dbName
spring.data.mongodb.host=192.168.30.100
spring.data.mongodb.port=27017
spring.data.mongodb.database=demo
代码:
@SpringBootTest
public class MongoTest {
@Autowired
private MongoTemplate mongoTemplate;
@Test
void test(){
this.mongoTemplate.createCollection("collection1");
}
}
实际操作过程:
引入依赖
配置
编写实体类:pojo类
@Document:作用在类上,标记对应的MongoDB的集合名称
@Id:作用在主键字段上,建议一定要有一个字段声明为id,_id
@Field:可以省略,除非字段名不一致
@Document("user")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
@Id // 建议一定要有一个字段定义为id,对应到_id
Long id;
@Field("username") // 该注解可以省略,如果字段名和MongoDB中字段名不一致,才需要指定
String name;
Integer age;
Boolean gender;
String pwd;
}
4.mongoTemplate实现文档的CRUD:数据库和集合都可以不用显式创建
// 新增一个 批量新增
@Test
void testInsert(){
this.mongoTemplate.insert(new User(1L, "柳岩", 20, false, "123456"));
}
// 更新
@Test
void testUpdate(){
// UpdateResult result = this.mongoTemplate.updateFirst(
UpdateResult result = this.mongoTemplate.updateMulti(
// Query.query(Criteria.where("age").gte(33)),
Query.query(Criteria.where("name").regex("小")),
Update.update("age", 30),
User.class);
System.out.println(result.getMatchedCount());
System.out.println(result.getModifiedCount());
}
// 删除
@Test
void testDelete(){
DeleteResult result = this.mongoTemplate.remove(Query.query(Criteria.where("age").lte(23)), User.class);
System.out.println(result.getDeletedCount());
}
5.查询条件:
this.mongoTemplate.find(Query对象)
Query对象的初始化:Query.query(Criteria)
Criteria对象的初始化:Criteria.where("key").is/gt/gte/lt/lte/ne/regex("value").and("key1").is("value1")
排序:Query.query().with(Sort.by(Order.asc/desc("key")))
分页:Query.query().skip((pageNum-1)*pageSize).limit(pageSize)
this.mongoTemplate.find(Query.query(Criteria.where("age").lte(30)
// .andOperator(Criteria.where("age").lte(34)) // 同一个字段使用多次,需要andOperator
.and("name").regex("小") // 如果是不同字段,一直向后进行and操作
.and("pwd").is("123456")
.orOperator(Criteria.where("name").regex("小")) // 得出的交集不是并集。
), User.class).forEach(System.out::println);
// 排序
this.mongoTemplate.find(Query
.query(Criteria.where("name").regex("小"))
.with(Sort.by(Sort.Order.asc("age")))
.skip(8).limit(4)
.with(PageRequest.of(2, 4)) // 页码从0开始
, User.class).forEach(System.out::println);