MongoDB的概念:
可扩展、高性能的 NoSQL 数据库,解决 web 应用提供高性能可扩展的数据存储的方案。
特点是高性能、易部署、易使用,存储数据(bson),主要特性有:
- 模式自由,支持动态查询、完全索引,可轻易查询文档中内嵌的对象及数组。
- 面向集合存储,易存储对象类型的数据 , 包括文档内嵌对象及数组。
- 高效的数据存储 , 支持二进制数据。
- 支持复制和故障恢复;提供了 主-从、主-主模式的数据复制及服务器之间的数据复制。
- 自动分片以支持云级别的伸缩性,支持水平的数据库集群,可动态添加额外的服务器。
MongoDB 优点:
- 性能优越:快速!在适量级的内存的 MongoDB 的性能是非常迅速的,它将热数据存储在物理内存中,使得热数据的读写变得十分快,
- 高扩展:第三方支持丰富(这是与其他的 No SQL 相比,MongoDB 也具有的优势)
- 自身的 Failover 机制!
- 弱一致性,能保证用户的访问速度
- 文档结构的存储方式,能够更便捷的获取数据: json 的存储格式
- 支持大容量的存储,内置 GridFS
- 内置 Sharding
MongoDB 缺点:
① MongoDB 不支持事务操作(最主要的缺点)
② MongoDB 占用空间过大(如果是大数据则提高性能需要以牺牲大量空间为代价)
③ MongoDB 没有如 MySQL 那样成熟的维护工具,这对于开发和IT运营都是个值得注意的地方(不支持复杂的sql)
**注意:**MongoDB 有一个最大的缺点,就是它占用的空间很大,因为它属于典型空间换时间原则的类型。那么它的磁盘空间比普通数据库会浪费一些,而且到目前为止它还没有实现在线压缩功能,在 MongoDB 中频繁的进行数据增删改时,如果记录变了,例如数据大小发生了变化,这时候容易产生一些数据碎片,出现碎片引发的结果,一个是索引会出现性能问题。
另外一个就是在一定的时间后,所占空间会莫明其妙地增大,所以要定期把数据库做修复,定期重新做索引,这样会提升MongoDB 的稳定性和效率。
@Document(“MongoDB库里的集合”) 的作用
//设置文档所在的集合
Redis、MongoDB、MySQL三者性能与数据量区别
数据量和性能的比较:
当物理内存够用的时候,Redis > MongoDB > MySQL
当物理内存不够用的时候,Redis 和 MongoDB 都会使用虚拟内存。
实际上如果Redis要开始虚拟内存,那很明显要么加内存条,要么你就该换个数据库了。
但是,MongoDB 不一样,只要,业务上能保证,冷热数据的读写比,使得热数据在物理内存中,mmap 的交换较少。
MongoDB 还是能够保证性能。有人使用 MongoDB 存储了上T的数据。
MySQL,MySQL根本就不需要担心数据量跟内存下的关系。不过,内存的量跟热数据的关系会极大地影响性能表现。
当物理内存和虚拟内存都不够用的时候,估计除了 MySQL 你没什么好选择了。
其实,从数据存储原理来看,我更倾向于将 MongoDB 归类为硬盘数据库,但是使用了 mmap 作为加速的手段而已。
MongoDB 与 MySQL 命令对比
传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成。
MongoDB 是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。MongoDB对于关系型数据库里的表,但是集合中没有列、行和关系概念,这体现了模式自由的特点。
Redis 与 MongoDB 内存管理机制
Redis 数据全部存在内存,定期写入磁盘,当内存不够时,可以选择指定的 LRU 算法删除数据。
MongoDB 数据存在内存,由 linux系统 mmap 实现,当内存不够时,只将热点数据放入内存,其他数据存在磁盘。
支持的数据结构
Redis 支持的数据结构丰富,包括hash、set、list等。
MongoDB 数据结构比较单一,但是支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富。
性能
二者性能都比较高,应该说都不会是瓶颈。
可靠性
二者均支持持久化。
集群
MongoDB 集群技术比较成熟,Redis从3.0开始支持集群。
适用的场景
- 评论系统
- 快递系统
- 游戏系统
- 日志系统
- …
不适用的场景
- 需要使用复杂sql的操作
- 事务性系统
MongoDB文档操作
控制台操作
/*
进入控制台运行sell命令
连接服务器: mongo ip:port
mongo localhost:27017
显示当前使用的数据库:
db
切换数据库: use 数据库名
use test
创建数据库
MongoDB没有专门的创建数据库的命令, 可以使用use 来选择某个数据库, 如果库不存在, 将会创建,但是只有往该库加入文档后才保存成文件
删除数据库:
db.dropDatabase(); //删除当前所在数据库
显示某个数据库的集合
show collections 或者 show tables
创建集合
MongoDB中,不用创建集合, 因为没有固定的结构, 直接使用db.集合名称.命令 来操作就可以了, 如果非要显示创建的话
使用: db.createCollection("集合名称")
*/
添加
document:类似json格式数据 {数据1:参数1,数据2:参数2,…}
document:类似json格式数据 [{数据1:参数1,数据2:参数2,…},{数据1:参数1,数据2:参数2,…},…]
document:表示保存到文档中去
options:可选择对应的要显示的集合元素,除了_id可任意选择 是0还是1之外,其余的要么全0要么全1,要么不输入则不显示。1表示要显示的,0表示不要显示的
db.集合名.insert(document, options)
添加或保存
document:类似json格式数据 {数据1:参数1,数据2:参数2,…}
document:类似json格式数据 [{数据1:参数1,数据2:参数2,…},{数据1:参数1,数据2:参数2,…},…]
document:表示保存到文档中去
options:可选择对应的要显示的集合元素,除了_id可任意选择 是0还是1之外,其余的要么全0要么全1,要么不输入则不显示。1表示要显示的,0表示不要显示的
//没有_id则进行添加,有__id则进行修改
db.集合名.save(document, options)
修改
filter:过滤条件
update:要进行修改的值
options:进行聚合操作
# 一次修改
db.users.updateOne(filter, update, options)
# 多次修改
db.users.updateMany(filter, update, options)
例子
一次只更新首条
db.users.updateOne({name:"xiaoming"}, {$set:{name:"xiaowu"}})
一次更新多个
db.users.updateMany(
{age:{ $lte: 20 }},
{$set:{name:"xiaoming",age:12}}
)
删除
filter:过滤条件
options:进行聚合操作
一次删除一条
db.users.deleteOne(filter, options)
一次删除多条
db.users.deleteMany(filter, options)
MongoDB查询操作
query:查询的过滤条件
projection:从document中查找特定的key/value pair,类似于关系型DB的where子句和select子句(主要显示类似sql那样指定的字段)
/*
{ xxx: <value>, field2: <value> ... }
MongoDB各条件查询格式
/*
“>”,“>=”,“<”,“<=”,"=","neq" 分别使用 gt,gt,gte,lt、lte、eq、neq 表示,格式是
{ xxx: { $lt: value} }
{ xxx: { $gt: value} }
{ xxx: { $lte: value} }
{ xxx: { $gte: value} }
{ xxx: { $eq: value} }
{ xxx: { $neq: value} }
逻辑或算符使用 $or 表示,格式是
{ $or: [ { <expression1> }, { <expression2> }, ... , { <expressionN> } ] }
逻辑与运算符使用“,” ,或者$and 表示,格式是
{ $and: [ { <expression1> }, { <expression2> } , ... , { <expressionN> } ] }
在范围内查询,使用 in表示,不在范围内,使用nin表示,格式是
{ xxx: { $in: [<value1>, <value2>, ... <valueN> ] } }
{ xxx: { $nin: [<value1>, <value2>, ... <valueN> ] } }
db.users.find({}).sort({xxx:1}) //正序
db.users.find({}).sort({xxx:-1}) //倒序
db.users.find({}).sort({xxx1:-1, xxx2:1}) //多列排序
//分页查询
db.users.find().skip(0).limit(3) //第一页
db.users.find().skip(3).limit(3) //第二页
db.users.find().skip((currentPage-1) * pageSize).limit(pageSize)
//模糊查询
//相当于 列 like '%关键字%'
db.集合.find( { 列: {$regex: /关键字/} } )
//格式
{列:/xxx/} --->%xxx%
{列:/^xxx/} --->xxx%
{列:/xxx$/} --->%xxx
{列:/xxx/i} 忽略大小写
详细去官网看
https://docs.mongodb.com/manual/reference/operator/query/
db.users.find(query, projection)
//多重条件模糊例子
//查name中包含fei字样,并且年龄在28 到 30间的用户信息,
//sql: select * from users where name like '%fei%' and age >= 28 and age <=30
db.users.find(
{$and: [{name: {$regex:/fei/}}, {age: {$gte:28, $lte:30}}]}
)
MongoDB文档设计
MongoDB的文档模式存储单位是一个文档,可以支持数组和嵌套文档,所以很多时候直接用一个这样的文档就可以涵盖这个客户相关的所有个人信息。
一般建议的是先考虑内嵌, 直接按照你的对象模型来设计你的数据模型。如果你的对象模型数量不多,关系不是很复杂,可能直接一种对象对应一个集合就可以了。
内嵌是文档模型的特色,可以充分利用MongoDB的富文档功能来处理一些文档模型的性能和扩展性等特性。一般的一对一、一对多关系,比如说一个人多个地址多个电话等等都可以放在一个文档里用内嵌来完成。
详细:MongoDB 进阶模式设计 | MongoDB中文社区 (mongoing.com)
springboot 操作MongoDB
传统相关的crud操作
@Autowired
private IUserService userService;
//添加
@Test
public void testSave(){
User user = new User();
user.setId(String.valueOf(21L));
user.set_id(String.valueOf(3L));
user.setName("dafei");
user.setAge(18);
userService.save(user);
}
//修改
@Test
public void testUpdate(){
User user = new User();
user.set_id("21");
user.setId("21");
user.setName("dafei2222");
user.setAge(18);
userService.update(user);
}
//删除
@Test
public void testDelete(){
userService.delete("21");
}
//查询单个
@Test
public void testGet(){
System.out.println(userService.get("21"));
}
//查询多个
@Test
public void testList(){
System.out.println(userService.list());
}
根据MongoDB的JPA规范
查询
构建限制条件
Criteria criteria = Criteria.where(“name”).is(“dafei”);
创建查询对象
Query query = new Query();
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Criteria;
@Autowired
private MongoTemplate mongoTemplate;
// 分页查询文档,显示第2页,每页显示3个,按照id升序排列
@Test
public void testQuery1() throws Exception {
// 创建查询对象
Query query = new Query();
// 设置分页信息
query.skip(3).limit(3);
// 设置排序规则
query.with(Sort.by(Sort.Direction.ASC,"id"));
//第一个参数为查询对象集合的过滤条件
//第二个参数为实体类的字节码对象
//第三个参数为MongoDB中的集合
List<User> list = mongoTemplate.find(query, User.class, "users");
list.forEach(System.err::println);
}
// 查询所有name为dafei的文档
//import org.springframework.data.mongodb.core.query.Criteria;
@Test
public void testQuery2() throws Exception {
// 构建限制条件 {"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);
}
@Autowired
private MongoTemplate mongoTemplate;
MongoCollection<实体类对象> collection = (MongoCollection<实体类对象>) this.mongoTemplate;
调用这个collection 对象里面的方法和数据库文件操作没有什么区别
SpringBoot集成MongoDB的命名规范例子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tM2RBdS4-1640834408773)(C:\Users\ljq\Desktop\笔记\mongoDB\6lcd9tjniu7k7pgtlgfovl414c.jpg)]
query.with()等价于limit查询