MongoDB介绍
什么是MongoDB
- 基于分布式文件存储数据库(就是一个数据库
- C++语言编写
- 支持的数据结构非常松散,是类似json的bson格式(后期插入修改数据写JSON
基本命令
- 数据库相关
1.查看所有数据库
show databases
2.选择数据库(如果数据库不存在,不会报错;会隐式创建:当后期该数据库有数据时自动创建)
use 数据库名
3.删除数据库(先选中数据库)
db.dropDatabase()
2.集合相关
1.查看所有集合
show collections
2.创建集合(插入数据会隐式创建)
db.createCollection('集合名')
3.删除集合
db.集合名.drop()
增删改查
1.增
语法:db.集合名.inset(JSON数据)
集合存在则插入,不存在则隐式创建
use test2
db.c1.insert({uname:"webopenfather",age:18})
注意:对象的键都不加引号,查看时集合数据时系统会自动加,且会给每条数据增加唯一ID键
1.自定义id
只需要给插入的JSON数据增加_id键即可覆盖(强烈不推荐)
db.c1.insert({_id:1,uname:"webopenfather",age:18})
2.一次插入多条记录
直接传输JSON格式数据
db.c1.insert([
{uname:"z3",age:3},
{uname:"z4",age:4},
])
3.快速插入多条数据
MongoDB底层使用JS引擎,支持部分JS语法
需求:在test2数据库c2集合中插入10条数据,分别是a1....a10
for(var i=1;i<10;i++){
db.c2.insert({uname:"a"+i,age:i})
}
2.查
语法:db.集合名.find(条件[,查询的列])
条件:
查询所有数据 {}或者不写
查询age=6 {age:6}
查询age=6且性别=男 {age:6,sex:'男'}
查询字段
不写 查询全部字段
{age:1} 只显示age字段
{age:0} 除了age字段都显示
注意:_id无论如何查询都显示
条件查询
db.集合名.find({键:值}) 值不直接写 {运算符:值}
db.集合名.find({
键:{运算符:值}
})
运算符 | 作用 |
---|---|
$gt | 大于 |
$gte | 大于等于 |
$lt | 小于 |
$lte | 小于等于 |
$ne | 不等于 |
$in | in |
$nin | not in |
3.改
语法:db.集合名.update(条件,新数据[,是否新增,是否修改多条])
是否新增:条件匹配不到数据则插入(true插入,false不插入)
是否修改多条:匹配成功数据修改(true是,false否 默认)
注意:若不使用修改器默认是将数据替换
修改器 | 作用 |
---|---|
$inc | 递增 |
$set | 修改字段值 |
$rename | 重命名列 |
$unset | 删除字段 |
db.集合名.update(条件,新数据)
{修改器:{键:值}}
4.删
语法:db.集合名.remove(条件[,是否删除一条])
是否删除一条:true是,false否全部删除 默认
排序、分页、聚合查询
排序sort、分页limit
db.集合名.find()
.sort({字段:1/-1}) 排序(1升-1降)
.skip(数字) 跳过指定条数
.limit(数字) 限制查询条数
.count() 统计总数
聚合查询
db.集合名.aggregate([
{管道:{表达式}}
...
])
常用管道
管道 | 作用 |
---|---|
$group | 将集合中文档分组,用于统计结果 |
$match | 过滤数据,只输出符合条件的文档 |
$sort | 聚合数据进一步排序 |
$skip | 跳过指定文档数 |
$limit | 限制集合数据返回文档数 |
常用表达式
表达式 | 作用 |
---|---|
$sum | 总和;$sum:1同count表示统计 |
$avg | 平均 |
$min | 最小值 |
$max | 最大值 |
求学生总数和平均年龄
db.c1.aggregate([
{
$group:{
_id:null, //_id必须有 null表示对全部数据分组
total_num:{$sum:1},
total_avg:{$avg:"$age"}
}
}
])
查询男生、女生人数,按人数升序
db.c1.aggregate([
{$group:{_id:"$sex",rs:{$sum:1}}},
{$sort:{rs:-1}}
])
索引
创建索引
_id是系统自建的索引,删除全部索引,也会保留_id
db.集合名.createIndex(待创建索引的字段[,额外选项/唯一索引等])
待创建索引的字段:{键:1,...,键:-1} 1升/-1降
额外选项:设置索引的名称或者唯一索引等
给name添加普通索引
db.c1.createIndex({name:1})
查询索引
db.集合名.getIndexes()
删除索引
全部删除:db.集合名.dropIndexes()
删除指定:db.集合名.dropIndex(索引名)
复合索引
db.集合名.createIndex({键1:方式,键2:方式})
给索引起名
db.集合名.createIndex({{键1:方式},{键1:"别名"}})
设置唯一索引
db.集合名.createIndex({{键1:方式},{unique:"键1"}})
分析索引
语法:db.集合名.find().explain('executionSrats')
stage状态:
- COLLSCAN 全表扫描
- IXSCAN 索引扫描
- FETCH 根据索引去检索指定document
权限机制
备份还原
SpringBoot集成MongoDB
1.构建SpringBoot项目
2.引入MongoDB依赖
3.在application.properties文件添加MongoDB配置(test库)
spring.data.mongodb.uri=mongodb://127.0.0.1:27017/test
MongoTemplate常用方法
方法 | 作用 |
---|---|
mongoTemplate.findAll(User.class) | 查询User文档的全部数据 |
mongoTemplate.findById(, User.class) | 查询User文档id为id的数据 |
mongoTemplate.find(query, User.class) | 根据query内的查询条件查询 |
mongoTemplate.upsert(query, update, User.class) | 修改 |
mongoTemplate.remove(query, User.class) | 删除 |
mongoTemplate.insert(User) | 新增 |
Query对象
1、创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
2、 精准条件:criteria.and(“key”).is(“条件”)
模糊条件:criteria.and(“key”).regex(“条件”)
3、封装条件:query.addCriteria(criteria)
4、大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
5、Query.addCriteria(new Criteria().andOperator(gt,lt));
6、一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
7、排序 :query.with(new Sort(Sort.Direction.ASC, “age”). and(new Sort(Sort.Direction.DESC, “date”)))
案例
- 创建实体类
MongoDB常用注解
注解 | 作用 |
---|---|
@Document | 标注在实体类上,标明由mongodb来维护该表。 |
@Id | 主键,不可重复,自带索引,需要自己生成并维护不重复的约束。 |
@Indexed | 索引,加索引后以该字段为条件检索将大大提高速度。 |
@Field | 定义存储字段名。可以不加,不加的话默认以参数名为列名。 |
@Transient | 被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性。 |
@DBRef | 设置对象的关联。类似于关系型数据库的外键 |
@Data
@Document("User")
public class User {
@Id
private String id;
private String name;
private Integer age;
private String email;
private String createDate;
}
*新增数据(mongoTemplate.insert(对象))
@Autowired
private MongoTemplate mongoTemplate;
//添加操作
@Test
void contextLoads() {
User user = new User();
user.setAge(20);
user.setName("test");
user.setEmail("[email protected]");
User user1 = mongoTemplate.insert(user);
System.out.println(user1);
}
- 查询全部数据(mongoTemplate.findAll(类.class))
//查询所有记录
@Test
public void findAll(){
List<User> all = mongoTemplate.findAll(User.class);
System.out.println(all);
}
- 根据id查询(mongoTemplate.findById(“id”, User.class))
//根据id查询
@Test
public void findId(){
User user = mongoTemplate.findById("60b4b3ca861699233d33f3e2", User.class);
System.out.println(user);
}
- 条件查询(mongoTemplate.find(query, User.class))
//条件查询
@Test
public void findUserList(){
Query query = new Query(Criteria.where("name").is("test").and("age").is(20));
List<User> users = mongoTemplate.find(query, User.class);
System.out.println(users);
}
- 模糊查询
//模糊条件查询
@Test
public void findLikeUserList(){
// name like test
String name = "est";
String regex = String.format("%s%s%s", "^.*", name, ".*$");
/*1、在使用Pattern.compile函数时,可以加入控制正则表达式的匹配行为的参数:
Pattern Pattern.compile(String regex, int flag)
2、regex设置匹配规则
3、Pattern.CASE_INSENSITIVE,这个标志能让表达式忽略大小写进行匹配。*/
Pattern pattern = Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
//创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
Query query = new Query(//构建查询条件
Criteria.where("name").regex(pattern));
List<User> users = mongoTemplate.find(query, User.class);
System.out.println(users);
}
- 分页查询
//分页查询(带条件)
@Test
public void pageLikeUserList(){
int pageNo = 1;//设置当前页
int pageSize = 3;//设置每页显示的记录数
//条件构建
String name = "est";
String regex = String.format("%s%s%s", "^.*", name, ".*$");
/*1、在使用Pattern.compile函数时,可以加入控制正则表达式的匹配行为的参数:
Pattern Pattern.compile(String regex, int flag)
2、regex设置匹配规则
3、Pattern.CASE_INSENSITIVE,这个标志能让表达式忽略大小写进行匹配。*/
Pattern pattern = Pattern.compile(regex,Pattern.CASE_INSENSITIVE);
//创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
Query query = new Query(//构建查询条件
Criteria.where("name").regex(pattern));
//分页构建
//查询数来集合(表)中的总记录数
long count = mongoTemplate.count(query, User.class);
List<User> users = mongoTemplate.find(
query.skip((pageNo - 1) * pageSize).limit(pageSize), User.class);
System.out.println(count);
System.out.println(users);
}
- 修改数据
//修改操作
@Test
public void updateUser(){
//根据id查询
User user = mongoTemplate.findById("60b4f89db925b61fbf529591", User.class);
//修改值
user.setName("test_02");
user.setAge(2);
user.setEmail("[email protected]");
//调用方法实现修改
Query query = new Query(Criteria.where("_id").is(user.getId()));
Update update = new Update();
update.set("name",user.getName());
update.set("age",user.getAge());
update.set("email",user.getEmail());
//调用mongoTemplate的修改方法实现修改
UpdateResult upsert = mongoTemplate.upsert(query, update, User.class);
long modifiedCount = upsert.getModifiedCount();//获取到修改受影响的行数
System.out.println("受影响的条数:"+modifiedCount);
}
- 删除数据
//删除条件
@Test
public void deleteUser(){
Query query = new Query(Criteria.where("_id").is("60b4b3ca861699233d33f3e2"));
DeleteResult remove = mongoTemplate.remove(query, User.class);
long deletedCount = remove.getDeletedCount();
System.out.println("删除的条数:"+deletedCount);
}//删除条件
@Test
public void deleteUser(){
Query query = new Query(Criteria.where("_id").is("60b4b3ca861699233d33f3e2"));
DeleteResult remove = mongoTemplate.remove(query, User.class);
long deletedCount = remove.getDeletedCount();
System.out.println("删除的条数:"+deletedCount);
}
- 索引
- 创建索引
@Test public void createAscendingIndex() { // 设置字段名称 String field = "name"; // 创建索引 升序 mongoTemplate.getCollection("user").createIndex(Indexes.ascending(field)); }
- 移除索引
@Test public void removeIndex() { // 设置字段名称 String field = "name"; // 删除索引 mongoTemplate.getCollection("user").dropIndex(field); }
- 查询所有索引
@Test public void getIndexAll() { // 获取集合中所有列表> ListIndexesIterable<Document> indexList = mongoTemplate.getCollection("user").listIndexes(); // 获取集合中全部索引信息 for (Document document : indexList) { System.out.println("索引列表:" + document); } }
MongoDB事务
单节点 mongodb 不支持事务,需要搭建 MongoDB 复制集