MongoDB
简介
什么是MongoDB?
- 一个以JSON为数据模型的文档非关系型数据库
为什么叫文档数据库?
- 文档来自与"JSON Document",并不是我们理解的PFD,WORD文档
MongoDB应用场景
- 游戏场景、物流、社交、视频直播、日志处理:存海量数据,不重要的数据,一定的查询性能
安装
https://www.mongodb.com/download-center/community
文档:https://spring.io/projects/spring-data-mongodb
MongoDB与Mysql对比
都是数据库概念,MongoDB没有主外键的概念
MongoDB | mysql |
---|---|
集合 | 表 |
文档 | 一条记录(行) |
文档中的key | 表字段 |
文档中的value | 字段值 |
指令
-
连接服务器:
mongo ip:port
例mongo localhost:27017 -
显示当前使用的数据库:
db
-
切换数据库:
use 数据库
-
创建数据库:没有创建数据库的命令,可以使用use选择数据库,不存在会自动帮我们创建,但是只有往该库加入文档才会保存成文件
-
显示某个数据库的集合:
show collections 或者 show tables
-
数据库与集合:MongoDB中没有固定结构,可以使用db.集合名称.命令 进行操作,需要显示创建可以使用
db.createCollection("集合名称")
-
删除文档:
remove : 可以按照条件来删除, 仅仅删除文档, 集合不删 ,db.集合名.remove(条件)不加条件删除所有文档
drop:会连带集合与索引一起删除
操作
添加insert
db.集合名.insert( 文档 )
: db.users.insert({id: 1, name: “xuan”, age: 22})
1.往集合中添加文档时,集合不存在会自动创建集合
2.操作成功时,集合会给文档生成一个 _id字段,也可以自己指定 "_id": ObjectId("60bb143c120c0000dd006fa2")
更新update
sql :update users ser xx=111 where xx=111
db.集合名.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>
}
)
---------------------------------------------------
参数解析:
1.query : update的查询条件,类似mysql中的 where条件
2.update:update的对象和一些更新的操作符(如$,$inc...)等 ,类似 set
3.upsert : 可选如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入
4.multi : 可选,默认是false:只更新找到第一条记录
true:条件查出来多条记录全部更新
5.writeConcern :可选, 设置复制集合存储策略
--------------------------------------------------------------
例子:
1.updateOne:
#把一个带有name=xuan,修改其age值为30
db.users.updateOne({name: "xuan"}, {$set: {age: 30}})
2.updateMany:
#修改所有name=xuan,修改其name=kent,age=23
db.users.updateMany({name:"xuan"},{$set:{name:"kent",age:23}})
#修改所有的文档,修改其name=yue,age=18
db.users.updateMany({}, {$set: {name: "yue", age: 18}})
删除remove/delete
db.集合名.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>
}
)
----------------------------------------
参数解析:
1.query :(可选)删除的文档的条件。
2.justOne :(可选)如果设为true或1,只删除一个文档.默认为false,删除所有匹配的条件
-----------------------------------------
简化方法:
1.删除1个:db.users.deleteOne({_id: ObjectId("xxx")})
2.删除所有:db.users.deleteMany({})
查询
find
sql :select age, name from table where …
db.集合名.find(query, projection)
参数解析:
1.query:条件
2.projection: 列的投影,指定返回哪些列 _id默认返回 eg: {"_id": 0}
-----------------------------------------------
#查所有用户
db.users.find()
#查看id,name 列 1表示显示,0表示不显示
//列挑选要注意,明确写出来的列(_id除外),要么都是0,要么都是1
db.users.find({},{id:1,name:1,_id:0})
排序sort
sort({列:1}) //正序
sort({列:-1}) //倒序
#查询所有用户按年龄排序
db.users.sort({age:1}) //asc
db.users.sort({age:-1}) //desc
##查询所有用户按年龄排序,年龄一样.使用id排序
db.users.sort({age:1,id:-1})
分页mimit
**sql: select * from users limit 0, 3 **
db.集合.find({}).skip(n).limit(m)
db.users.find().skip((currentPage-1) * pageSize).limit(pageSize)
第一页
db.users.find({}).skip(0).limit(3)
第二页
db.users.find({}).skip((2-1)*3).limit(3)
第三页
db.users.find({}).skip((3-1)*3).limit(3)
比较运算符
- **大于 : $gt **
- < 小于 : $lt
- = 大于等于 : $gte
- <= 小于等于 : $lte
- != 不等 : $ne
#查询age >30的用户
db.users.find( { age:{$gt:30} } )
#查询名字为xuan或者yue 用户
db.users.find(
{ name:{$in: ["xuan","yue"]} }
)
判断指定列是否存在exist
#查询拥有name列的属性
db.users.find(
{ name:{$exists:false } }
)
逻辑运算符
- && 与 : $and
- || 或 : $or
- ! 非 : $not
SQL | MQL |
---|---|
a=1 AND b=2 | { $and: [ {a:1}, {b:2} ] } 或者 { a:1 ,b:2 } |
a=1 ORb=2 | { $or: [ {a:1}, {b:2} ] } |
a is null | {a : {$exists:false } } |
a in (1,2,3) | {a : {$in:[1,2,3] } } |
find({逻辑操作符:[条件1,条件2,....]})
--------------------------------------
#查询年龄在25到30间的用户信息
db.users.find(
{ $and:[{age:{$gte:25}},{age:{$lte:30}] }
)
简写:
db.users.find(
{ age:{$gte:25,$lte:30} }
)
模糊查询
sql :select * from user where name like '%关键字%'
- {name:/xxx/} —>%xxx%
- {name:/^xxx/} —>xxx%
- {name:/xxx$/} —>%xxx
- {name:/xxx/i} 忽略大小写
db.集合.find( { 列: {$regex: /关键字/} } ) #正则对象(js)
db.集合.find({列: {$regex: "关键字"}})
#查询name带有ent的用户信息
db.users.find(
{name: {$regex:/ent/ }}
)
#查name中包含k字样,并且年龄在20 到 25间的用户信息
db.users.find(
{$and: [{name: {$regex:/k/}}, {age: {$gte:20, $lte:25}}]}
)
文档设计
- 普通文档
- 文档嵌套
- 数组方式
待补充…
集成Springboot注意点
mongoDB接口定义:
1.自定义接口,继承MongoRepository
2.添加2个泛型:
泛型1:操作实体对象User
泛型2:实体主键id类型String
问题点1:
UserRepository 没有定义curd方法为啥可以在service层调用crud方法操作?
因为UserRepository继承了MongoRepository接口,而有了crud方法
问题点2:
没有包扫描,为什么UserRepository接口就有实现类ne?
spring-boot-data-MongoDB 这个框架在项目启动的时候会自动扫描所有UserRepository接口的子接口,自动动态代理创建对象,交给容器管理
问题3:
直接在接口中定义findByName方法,就可以直接调用了,而不需要进行实现,怎么做到?
上面操作跟 JPA查询方法定义 规范有关
spring-boot-data-MongoDB 这个框架实现了JPA规范
依赖:
<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</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>
代码:
1.实体类User
@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<>();
}
----------------------------------------
2.接口repository
public interface UserMongoRepository extends MongoRepository<User,String> {
}
-----------------------------------------
3.实现类接口 与实现类
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 UserMongoRepository 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();
}
}
JPA
JPA查询方法规范约定:前缀+操作符+属性
- 前缀: find /query
- 操作符:by and or …
- 属性:表的列 /domain属性
局限性:JPA查询规范有一定限制,查询条件不能太多,只能用于简单少量的查询高级查询,多条件查询就不行了,可以使用mongoTemplate拼接MQL查询语句