MongDB – Spring data Jpa
文章目录
1.mongodb
1.1 简介
1.MongoDB是一个基于分布式文件存储的数据库。
2.MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
3.它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。
4.Mongo最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
5.MongoDB属于NoSQL数据库,自然也是没有表相关概念的,该数据库存储使用的是集合,集合中存储的是文档(树状结构数据)
1.2 特点
- 高性能
- 易部署
- 易使用
- 非常方便的存储数据
2.安装及navict安装
安装包+破解---->视频
navicat12开始支持mongodb
基本语法
show dbs: 查询所有数据库
use 数据库名: 创建并且选中数据库,数据库已经存在则直接选中
db: 查询当前选择的数据库
db.dropDatabase(): 删除当前选中的数据库
show collections: 查询当前库中的集合
db.createCollection("集合名"): 创建集合
db.集合名.drop(): 删除集合
3.操作
3.1新增
//往集合中新增文档,当集合不存在时会自动先创建集合
db.集合名.insert( 文档 ) 往集合中插入一个文档
例:db.user.insert({id: 1, name: "bunny", age: 20});
(当操作成功时,集合会给文档生成一个**_id**字段,该字段就是文档的主键)
3.2更新
db.集合名.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
简化方法:
更新1个:db.集合名.updateOne( ... )
更新所有:db.集合名.updateMany( ... )
//**query** : update的查询条件,类似sql update查询内where后面的。
//**update** : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
//**upsert** : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
//**multi** : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
//**writeConcern** :可选,抛出异常的级别
例:db.user.update(
{
name:"bunny"
},
{$set:{
age:233
}},
{
multi:true
}
);
3.3删除
db.集合名.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
简化方法:
删除1个:db.集合名.deleteOne( ... )
删除所有:db.集合名.deleteMany( ... )
//**query** :(可选)删除的文档的条件。
//**justOne** : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
//**writeConcern** :(可选)抛出异常的级别
例:db.user.deleteMany(
{name:"wangwu"}
);
//remove() 方法 并不会真正释放空间。需要继续执行 db.repairDatabase() 来回收磁盘空间。
db.repairDatabase()
db.runCommand({ repairDatabase: 1 })
3.4 查询
db.集合名.find(query, projection)
//参数1:查询操作符指定查询条件
//参数2:通过0,1来指定是否要,某一列 (映射的列必须同时0或1)
例://查所有
db.users.find()
db.users.find({},{_id:0,name:1}) //只显示name列
3.4.1排序查询
db.users.find({}).sort({字段: 1}) -> 按照字段升序排列
db.users.find({}).sort({字段: -1}) -> 按照字段降序排列
例://按照年龄排序 //1正序,-1倒叙
db.users.find({}).sort({age:1}); //正序
3.4.2分页查询
db.users.find({}).skip(pagesize*(currentpage - 1)).limit(5);
db.users.find({}).sort({id:-1}).skip(0).limit(5); //先进行排序,再分页
//skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序是先 sort(), 然后是 skip(),最后是显示的 limit()。
3.5高级查询
3.5.1比较操作符
//带条件的查询
//>操作
//语法 -> find( {字段: {比较操作符: 值, ...}} )
//> 大于 - $gt greate than
//< 小于 - $lt less
//>= 大于等于 - $gte equals
//<= 小于等于 - $lte
//!= 不等 - $ne
// {$exists: false} 查询指定列存在不存在
//in {$in: [xx, xx ...]}
例:db.users.find(
{
age:{$gt:30}
}
);
db.users.find({
name:{
$in:["dafei","will"]
}
})
3.5.2逻辑操作符
语法 -> find({列:{逻辑操作符: [条件1, 条件2, ...]}})
- (&&) 与 - $and
- (||) 或 - $or
- (!) 非 - $not
例://and
db.users.find({
$and:[
{age:{$gte:30}},
{age:{$lte:32}}
]
})
//or
//查询所有age<28,age>30的文档
db.users.find({
$or:[
{age:{$gte:30}},
{age:{$lte:28}}
]
})
//$not
//语法: { field: { $not: { <operator-expression> } } }
//$not执行一个逻辑not操作在指定的表达式并查询到不匹配表达式的文档,这包含不包括字段的文档;
$not操作符只会影响其他操作符不能独立检查字段和文档,因此使用$not做逻辑析取和$ne操作测试字段内容
使用$not操作时考虑如下操作:
1.操作$not操作符和其它操作符一致但是会产生一些意想不到的结果,比如数组之类的数据类型;
2.$not操作符不支持$regex正则表达式操作,使用//或者你的驱动接口代替,使用语言的正则表达式功能创建正则表达式对象;
3.5.3模糊查询
//模糊查询
//db.集合.find({列: {$regex: /关键字/}})
//sql: select * from user where name like '%%'
//{name:/xxx/} --->%xxx%
//{name:/^xxx/} --->xxx%
//{name:/xxx$/} --->%xxx
//{name:/xxx/i} 忽略大小写
例://正则表达式对象
db.users.find({
name:{$regex:/fei/}
})
//正则表达式字符串
db.users.find({
name:{$regex:".*fei.*"}
})
3.6 数组查询
3.6.1 添加
//向数组里添加 $push $addToset
//给dafei添加一个java
// $push // 可以一次添加多个值,但是可以重复
db.users.updateMany({name:"dafei"},{$push:{hobby:"java"}})
db.users.updateMany(
{name:"dafei"},
{$push:{hobby:{$each:["java","c","c++"]}}}
)
// $addToset 不会重复
db.users.updateMany(
{name:"dafei"},
{
$addToSet:{hobby:"go"}
}
)
//不可取 //会将 ["go","c"] 作为一个值提交
db.users.updateMany(
{name:"dafei"},
{
$addToSet:{hobby:["go","c"]}
}
)
3.6.2 删除
//删除 $pop $pull
//删除最后一个 1--最后一个 -1--第一个
// $pop 局限: 只能从头或者从尾删除, 不能通过指定元素删除
db.users.updateMany(
{name:"dafei"},
{
$pop:{hobby:-1}
}
)
db.users.updateMany(
{name:"dafei"},
{
$pop:{hobby:1}
}
)
//$pull 删除数组中数据, 通过指定内容删除
//按内容删除
db.users.updateMany(
{name:"dafei"},
{
$pull:{hobby:"java"}
}
)
3.6.3 修改
//改值 $set:{"hobby.1":"java"} $set:{"hobby.$":"c"}
//通过索引修改
db.users.updateMany(
{name:"dafei"},
{
$set:{"hobby.1":"java"}
}
)
//通过内容
db.users.updateMany(
{name:"dafei",hobby:"go"},
{
$set:{"hobby.$":"c"}
}
)
3.6.4 查询
//查询
db.users.find({
name:"dafei"
})
4.聚合操作
聚合框架
什么是Mongodb聚合框架
MongoDB聚合框架(Aggregation Framewordk) 是一个计算框架,他可以作用在一个或集合集合中对集合中的数据进行一系列运算,将这些数据转化为期望的形式
从效果而言, 聚合框架相当于SQL查询中
Group by left join
管道(Pipeline) 与 步骤(Stage)
整个聚合运算工程称之为管道, 它是由多个步骤组成
每个管道:
1:接收一系列文档(原始数据)
2:每一个步骤对这些文档进行一系列运算
3:结果文档输出给下一个步骤
基本语法:
pipeline = [$stage1, $stage2, .... $stageN]
db.集合.aggregate(
pipeline,
{
options
}
)
eg:
db.user.aggregate(
[
{
$group:{
_id:"$name",
namecount:{$sum:1}
}
}
]
);
$project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
$match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
$limit:用来限制MongoDB聚合管道返回的文档数。
$skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
$group:将集合中的文档分组,可用于统计结果。
$sort:将输入文档排序后输出。
$unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
$geoNear:输出接近某一地理位置的有序文档。
4.文档设计
4.1三 泛式
解释:
1NF:原子性 字段不可再分,否则就不是关系数据库; ------------字段不可分;
2NF:唯一性 要求数据库表中的每个实例或行必须可以被惟一的区分; -----有主键,非主键字段依赖主键,不能部分依赖;
3NF:每列都与主键有直接关系,不存在传递依赖; -------非主键字段不能相互依赖;
关系数据库:
开发中设计表需要满足第三方式即可,但是,实际开发很多
时候使用打破第三范式操作
真实开发设计:针对频繁查询表,使用冗余字段方式(打破第三范式)
优点:查询很快缺点: DML操作麻烦
4.2 反泛式
使用冗余字段方式替换关联映射
使用数组方式替换一对多
mongodb 文档关系设计
一对一 冗余字段
qq{
id,num,url
}
多对一 缺陷:没有部门列表/查询操作 员工与部门独立,采用冗余字段方式处理
employee{ employee { dept{
id,name, id,name, id,name,
dept:{ deptName }
id,name deptId
} }
}
一对多 (不能有太多) (可以很多)
dept{ employee{ dept{ employee{
id,name id,name id,name id,name
esList:{ } esList:{ }
{id,name}, employee_id,
{id,name}... employee_id...
} }
}
多对多 (同一对多)
5.集成springboot
5.1依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<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>
5.2配置
# 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
5.3后端
1.domain 贴 @Document("users") //设置文档所在的集合
2.domain private ObjectId _id;字段 贴@Id //文档的id使用ObjectId类型来封装,并且贴上@Id注解
3.写service 及 impl
4.写UserRepository 继承 MongoRepository<User,String>
/**
* 1.定义一个接口
* 2.继承MongoRepository
* 3.指定2个泛型 泛型1:该接口操作实体 泛型2:实体的主键类型
* 4.贴一个@Repository 可以不贴
*/
5.写crud测试
增 service.save(user);
改 //先查询 //再替换 //再更新
User user = service.get("5edb3dea770c456b8fda2888");
user.setName("lisi");
service.save(user);
删 service.delete("5ed9eacac01b0000d600027c");
查一个 service.get("5ed9eacac01b0000d600027c")
查所有 service.selectAll()
5.4 Jpa规范
方法名要求:前缀 + 实体类属性名(表的列名)
前缀: findBy queryBy
· Spring Data方法命名规范
| 关键字 | 例子 | JPQL |
| :--------------: | :----------------------------------------: | :-----------------------------: |
| And | findByNameAndAge(String name, Integer age) | where name = ? and age = ? |
| Or | findByNameOrAge(String name, Integer age) | where name = ? or age = ? |
| Is | findByName(String name) | where name = ? |
| Between | findByAgeBetween(Integer min, Integer max) | where age between ? and ? |
| LessThan | findByAgeLessThan(Integer age) | where age < ? |
| LessThanEqual | findByAgeLessThanEqual(Integer age) | where age <= ? |
| GreaterThan | findByAgeGreaterThan(Integer age) | where age > ? |
| GreaterThanEqual | findByAgeGreaterThanEqual(Integer age) | where age >= ? |
| After | 等同于GreaterThan | |
| Before | 等同于LessThan | |
| IsNull | findByNameIsNull() | where name is null |
| IsNotNull | findByNameIsNotNull() | where name is not null |
| Like | findByNameLike(String name) | where name like ? |
| NotLike | findByNameNotLike(String name) | where name not like ? |
| StartingWith | findByNameStartingWith(String name) | where name like '?%' |
| EndingWith | findByNameEndingWith(String name) | where name like '%?' |
| Containing | findByNameContaining(String name) | where name like '%?%' |
| OrderByXx[desc] | findByIdOrderByXx[Desc] (Long id) | where id = ? order by Xx [desc] |
| Not | findByNameNot(String name) | where name != ? |
| In | findByIdIn(List\<Long\> ids) | where id in ( ... ) |
| NotIn | findByIdNotIn(List\<Long\> ids) | where id not in ( ... ) |
| True | findByXxTrue() | where Xx = true |
| False | findByXxFalse() | where Xx = false |
| IgnoreCase | findByNameIgnoreCase(String name) | where name = ? (忽略大小写) |
5.5 分页查询
@Autowired
private MongoTemplate mongoTemplate;
// 创建查询对象 (核心) (拼接Mql语句)
Query query = new Query();
/*//第一种分页
// 设置分页信息
query.skip(3).limit(3);
// 设置排序规则
query.with(Sort.by(Sort.Direction.ASC,"id"));*/
//第二种分页
// ( 当前页(0开始), 每页显示数 ,排序规则 ,排序字段 )
Pageable of = PageRequest.of(1, 3, Sort.Direction.ASC, "id");
query.with(of);
List<User> list = mongoTemplate.find(query, User.class, "users");
list.forEach(System.err::println);
5.6条件
普通条件
// 构建限制条件 {"name": "dafei"}
Criteria criteria = Criteria.where("name").is("dafei");
// 创建查询对象
Query query = new Query();
// 添加限制条件
query.addCriteria(criteria);
List<User> list = mongoTemplate.find(query, User.class, "users");
list.forEach(System.err::println);
or:
Criteria criteria = new Criteria().orOperator(
Criteria.where("name").is("dafei"),
Criteria.where("age").lt(30)
);
and:
Criteria criteria = new Criteria().andOperator(
Criteria.where("name").regex(".*fei.*"),
Criteria.where("age").gte(30).lte(32)
);
版权声明:本文为qq_45627063原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。