特点
(1)高性能: MongoDB提供高性能的数据持久性。特别是, 对嵌入式数据模型的支持减少了数据库系统上的I/O活动。 索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。(文本索引解决搜索的需求、TTL索引解决历史数据自动过期的需求、地 理位置索引可用于构建各种 O2O 应用) mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求。 Gridfs解决文件存储的需求。
(2)高可用性: MongoDB的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余。
(3)高扩展性: MongoDB提供了水平可扩展性作为其核心功能的一部分。 分片将数据分布在一组集群的机器上。(海量数据存储,服务能力水平扩展) 从3.4开始,MongoDB支持基于片键创建数据区域。在一个平衡的集群中,MongoDB将一个区域所覆盖的读写只定向到该区域内的那些 片。
(4)丰富的查询支持: MongoDB支持丰富的查询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等。
(5)其他特点:如无模式(动态模式)、灵活的文档模型、
NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。
在现代的计算系统上每天网络上都会产生庞大的数据量。
这些数据有很大一部分是由关系数据库管理系统(RDBMS)来处理。 1970年 E.F.Codd's提出的关系模型的论文 "A relational model of data for large shared data banks",这使得数据建模和应用程序编程更加简单。
通过应用实践证明,关系模型是非常适合于客户服务器编程,远远超出预期的利益,今天它是结构化数据存储在网络和商务应用的主导技术。
NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。
和redis的区别是redis更多利用的是缓存,而MongoDB更多利用的是磁盘
启动MongoDB
ongod --dbpath=..\data\db
指定数据库地址进行启动
mongod --config ../config/mongod.conf
指定配置文件启动
如果发生48错误,说明bindip地址写错了
学习的时候建议使用 0.0.0.0 也就是不限制ip
增删改查
增
db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明 媚","userid":"1001","nickname":"Rose","createdatetime":new Date(),"likenum":NumberInt(10),"state":null})
查
db.comment.find({},{userid:1,nickname:1})
查找所有的数据,并且只显示userid 和nickname字段
改
覆盖修改
db.comment.update({_id:"1"},{likenum:NumberInt(1001)})
直接修改
db.comment.update({_id:"2"},{$set:{likenum:NumberInt(889)}})
在后面加上{multi:true})表示userid=1003的所有人的nickname都改为凯撒大帝默认只改变一个
db.comment.update({userid:"1003"},{$set:{nickname:"凯撒大帝"}},{multi:true})
使用$inc对值进行增长
db.comment.update({_id:"3"},{$inc:{likenum:NumberInt(1)}})
删
db.comment.deleteOne({"_id": ObjectId("64cb20f950440c6ce703d027")})
前面填写id,后面填写选项
db.集合名称.remove(条件)
排序
//升序为1
//降序为-1
db.comment.find().sort({"articleid":1})
查询条件
正则匹配
db.comment.find({nickname:/^O/})
大于查询
db.comment.find({likenum: {$gt: 500}})
范围查询
db.comment.find({"likenum": {$in: [732,710]}})
db.comment.find({userid:{$nin:["1003","1004"]}})
条件连接查询
db.comment.find({$and:[{likenum:{$gte:NumberInt(700)}},{likenum:{$lt:NumberInt(2000)}}]})
总结
条件
{articleid: "100001"}
字段名
{nickname: /^O/}
索引
索引支持在MongoDB中高效地执行查询。如果没有索引,MongoDB必须执行全集合扫描,即扫描集合中的每个文档,以选择与查询语句 匹配的文档。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非 常致命的。 如果查询存在适当的索引,MongoDB可以使用该索引限制必须检查的文档数。 索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排 序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB还可以使用索引中的排序返回排序结果。 官网文档:https://docs.mongodb.com/manual/indexes/ 了解: MongoDB索引使用B树数据结构(确切的说是B-Tree,MySQL是B+Tree)
索引的增删改查
查
db.集合名.getIndexs()
查出来一个数组
v 表示版本号
key 表示在哪个字段上加了索引
name 表示索引名称
ns 索引存放在哪个集合里面
增
db.comment.createIndex(keys, options)
索引建立成功
复合索引创建成功
删
提示: _id 的字段的索引是无法删除的,只能删除非 _id 字段的索引。
explain()
在find语句后面添加.explain()可以对查询进行解析
实战训练
mongodb-driver
相当于JDBC
SpringDataMongoDB
相当于mabatis
三个注解
@Document
@Document(collection="comment")
//把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。 //@Document(collection="mongodb 对应 collection 名") // 若未加 @Document ,该 bean save 到 mongo 的 comment collection // 若添加 @Document ,则 save 到 comment collection
@Id
表示主键
@Field("content")
表示映射在表中的值
@Indexed
表示一个索引
Dao层
@Repository
public interface CommentRepository extends MongoRepository<Comment,String> {
}
Service层
@Service
public class CommentService {
//注入dao
@Autowired
private CommentRepository commentRepository;
/**
* 保存一个评论
* @param comment
*/
public void saveComment(Comment comment){
//如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键
//设置一些默认初始值。。。
//调用dao
commentRepository.save(comment);
}
/**
* 更新评论
* @param comment
*/
public void updateComment(Comment comment){
//调用dao
commentRepository.save(comment);
}
/**
* 根据id删除评论
* @param id
*/
public void deleteCommentById(String id){
//调用dao
commentRepository.deleteById(id);
}
/**
* 查询所有评论
* @return
*/
public List<Comment> findCommentList(){
//调用dao
return commentRepository.findAll();
}
/**
* 根据id查询评论
* @param id
* @return
*/
public Comment findCommentById(String id){
//调用dao
return commentRepository.findById(id).get();
}
}
测试
//SpringBoot的Junit集成测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class CommentServiceTest {
@Autowired
private CommentService commentService;
@Test
public void testSaveComment(){
Comment comment=new Comment();
comment.setArticleid("100000");
comment.setContent("测试添加的数据");
comment.setCreatedatetime(LocalDateTime.now());
comment.setUserid("1003");
comment.setNickname("凯撒大帝");
comment.setState("1");
comment.setLikenum(0);
comment.setReplynum(0);
commentService.saveComment(comment);
}
@Test
public void testFindAll(){
List<Comment> list = commentService.findCommentList();
list.forEach(System.out::println);
}
@Test
public void testFindCommentById(){
Comment comment = commentService.findCommentById("64cb467f50440c6ce703d033");
System.out.println(comment);
}
}
分页
自定义页数查询 注意 方法名不可以随便修改
Page<Comment> findByParentid(String id, Pageable pageable);
MongoTemplate
public void updateCommentLikenum(String id) {
Query query = new Query(Criteria.where("_id").is(id));
Update update = new Update();
update.inc("likenum");
mongoTemplate.updateFirst(query,update,Comment.class);
}
副本集-replicaSet
MongoDB中的副本集(Replica Set)是一组维护相同数据集的mongod服务。 副本集可提供冗余和高 可用性,是所有生产部署的基础。
复制提供冗余并提高数据可用性。 通过在不同数据库服务器上提供多个数据副本,复制可提供一定级别 的容错功能,以防止丢失单个数据库服务器。
有点像是读写分离
先写配置文件
systemLog:
#MongoDB发送所有日志输出的目标指定为文件
destination: file
#mongod或mongos应向其发送所有诊断日志记录信息的日志文件的路径
path: "/mongodb/replica_sets/myrs_27019/log/mongod.log"
#当mongos或mongod实例重新启动时,mongos或mongod会将新条目附加到现有日志文件的末尾。
logAppend: true
storage:
#mongod实例存储其数据的目录。storage.dbPath设置仅适用于mongod。
dbPath: "/mongodb/replica_sets/myrs_27019/data/db"
journal:
#启用或禁用持久性日志以确保数据文件保持有效和可恢复。
enabled: true
processManagement:
#启用在后台运行mongos或mongod进程的守护进程模式。
fork: true
#指定用于保存mongos或mongod进程的进程ID的文件位置,其中mongos或mongod将写入其PID
pidFilePath: "/mongodb/replica_sets/myrs_27019/log/mongod.pid"
net:
#服务实例绑定所有IP,有副作用,副本集初始化的时候,节点名字会自动设置为本地域名,而不是ip
#bindIpAll: true
#服务实例绑定的IP
bindIp: 0.0.0.0
#bindIp
#绑定的端口
port: 27019
replication:
#副本集的名称
replSetName: myrs
写三份
注意修改一下端口
主节点使用rs.add(host, arbiterOnly)添加节点 arbiterOnly设置为true 则这个节点为仲裁节点
rs.add(host, arbiterOnly)
副节点需要接收主节点的申请
rs.slaveOk()
连接
navicat
var config = rs.config(); config.members[0].host="192.168.232.122:27017";rs.reconfig(config)
需要先修改ip地址
SpringDataMongoDB
mongodb://host1,host2,host3/articledb? connect=replicaSet&slaveOk=true&replicaSet=副本集名字
分片集群-Sharded Cluster
分片(sharding)是一种跨多台机器分布数据的方法, MongoDB使用分片来支持具有非常大的数据集 和高吞吐量操作的部署。
换句话说:分片(sharding)是指将数据拆分,将其分散存在不同的机器上的过程。有时也用分区 (partitioning)来表示这个概念。将数据分散到不同的机器上,不需要功能强大的大型计算机就可以储存 更多的数据,处理更多的负载。
MongoDB分片群集包含以下组件: 分片(存储):每个分片包含分片数据的子集。 每个分片都可以部署为副本集。 mongos(路由):mongos充当查询路由器,在客户端应用程序和分片集群之间提供接口。 config servers(“调度”的配置):配置服务器存储群集的元数据和配置设置。 从MongoDB 3.4开 始,必须将配置服务器部署为副本集(CSRS)。
添加分片副本集
sh.addShard("myshardrs01/192.168.0.2:27018,180.76.159.126:27118,180.76.159.126:2 7218")
查看分片状态
sh.status()
进行分片
sh.shardCollection("articledb.comment",{"nickname":"hashed"})
1)一个集合只能指定一个片键,否则报错。
2)一旦对一个集合分片,分片键和分片值就不可改变。 如:不能给集合选择不同的分片键、不能更新 分片键的值。
3)根据age索引进行分配数据。