目录
引入依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-mongodb</artifactId> </dependency>
在application.yml中写配资
spring: data: mongodb: # 主机地址 host: 47.115.217.159 # 端口 port: 27017 # 数据库名称 database: test
启动项目,如果成功启动,说明基础配资没有问题
搭建实体类
MongoDB中的集合结构
字段名称 | 字段含义 | 字段类型 | 备注 |
---|---|---|---|
_id | ID | ObjectId或String | Mongo的主键字段,唯一标识每条评论记录 |
articleid | 文章ID | String | 评论所属文章的唯一标识符 |
content | 评论内容 | String | 用户发表的评论内容 |
userid | 评论人ID | String | 发表评论的用户的唯一标识符 |
nickname | 评论人昵称 | String | 发表评论的用户昵称 |
createdatetime | 评论的日期时间 | Date | 评论创建的时间戳 |
likenum | 点赞数 | Int32 | 评论获得的点赞数量 |
replynum | 回复数 | Int32 | 评论收到的回复数量 |
state | 状态 | String | 评论的状态,"0"表示不可见,"1"表示可见 |
parentid | 上级ID | String | 如果为"0",表示这是文章的顶级评论;否则,表示这是对另一条评论的回复 |
实体类
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
/**
* 文章评论实体类
*/
//把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。
//@Document(collection="mongodb 对应 collection 名")
@Document(collection="comment")//可以省略,如果省略,则默认使用类名小写映射集合
//复合索引
// @CompoundIndex( def = "{'userid': 1, 'nickname': -1}")
@Data
@ToString
public class Comment implements Serializable {
//主键标识,该属性的值会自动对应mongodb的主键字段"_id",如果该属性名就叫“id”,则该注解可以省略,否则必须写
@Id
private String id;//主键
//该属性对应mongodb的字段的名字,如果一致,则无需该注解
@Field("content")
private String content;//吐槽内容
private Date publishtime;//发布日期
//添加了一个单字段的索引
@Indexed
private String userid;//发布人ID
private String nickname;//昵称
private LocalDateTime createdatetime;//评论的日期时间
private Integer likenum;//点赞数
private Integer replynum;//回复数
private String state;//状态
private String parentid;//上级ID
private String articleid;
}
说明:
索引可以大大提升查询效率,一般在查询字段上添加索引,索引的添加可以通过Mongo的命令来添加,也可以在Java的实体类中通过注解添加。
1)单字段索引注解@Indexed
声明该字段需要索引,建索引可以大大的提高查询效率。
2)复合索引注解@CompoundIndex
复合索引的声明,建复合索引可以有效地提高多字段的查询效率。
基本的增删改查操作
(1)创建数据访问接口
public interface CommentDao extends MongoRepository<Comment,String> {
}
MongoRepository这个类它封装了很多基本的MongoDB操作,类似于关系型数据库的mybatis-plus。
(2)创建业务逻辑类
@Service
public class CommentService {
//注入dao
@Autowired
private CommentDao commentDao;
/**
* 保存一个评论
* @param comment
*/
public void saveComment(Comment comment){
//如果需要自定义主键,可以在这里指定主键;如果不指定主键,MongoDB会自动生成主键
//设置一些默认初始值。。。
//调用dao
commentDao.save(comment);
}
/**
* 更新评论
* @param comment
*/
public void updateComment(Comment comment){
//调用dao
commentDao.save(comment);
}
/**
* 根据id删除评论
* @param id
*/
public void deleteCommentById(String id){
//调用dao
commentDao.deleteById(id);
}
/**
* 查询所有评论
* @return
*/
public List<Comment> findCommentList(){
//调用dao
return commentDao.findAll();
}
/**
* 根据id查询评论
* @param id
* @return
*/
public Comment findCommentById(String id){
//调用dao
return commentDao.findById(id).get();
}
}
(3)新建测试类,测试保存和查询所有:
@SpringBootTest
class ApplicationTests {
//注入Service
@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();
for (Comment comment : list) {
System.out.println(comment);
}
}
/**
* 测试根据id查询
*/
@Test
public void testFindCommentById(){
Comment comment = commentService.findCommentById("1");
System.out.println(comment);
}
}
保存评论测试结果:
查询所有评论测试结果
根据Id查询测试结果
分页查询
需求:查询UserId相同的全部数据,并且分页显示
实现:
(1)CommentDao新增方法定义
@Repository
public interface CommentDao extends MongoRepository<Comment,String> {
Page<Comment> findAllByUserid(String userid, Pageable pageable);
}
这里面定义方法必须按照指定的格式来定义,比如想要查询方法,就需要以findBy开头,By后面的要与形参的第一个参数名称相同。
(2)CommentService新增方法
public Page<Comment> findCommentByUserId(String id,int page, int size){ return commentDao.findAllByUserid(id,PageRequest.of(page-1, size)); }
(3)测试用例
@Test
public void testFindCommentListPageByParentid(){
Page<Comment> pageResponse = commentService.findCommentByUserId( "1003",1, 2);
System.out.println("----总记录数:"+pageResponse.getTotalElements());
System.out.println("----当前页数据:");
for (Comment comment : pageResponse.getContent()) {
System.out.println(comment);
}
}
运行结果
使用MongoTemplate实现复杂的功能
前面MongoDB自动提供的那些功能都比较基础,功能都比较单一,如果要实现功能性复杂一点的语句,就需要借助MongoTemplate来实现。
需求:将指定id的likenum加1
根据上面的基本功能实现
/**
* 点赞-效率低
* @param id
*/
public void updateCommentThumbupToIncrementingOld(String id){
Comment comment = CommentRepository.findById(id).get();
comment.setLikenum(comment.getLikenum()+1);
CommentRepository.save(comment);
}
以上方法虽然实现起来比较简单,但是执行效率并不高,因为我只需要将点赞数加1就可以了,没必要查询出所有字段修改后再更新所有字段。
所以使用MongoTemplate实现
实现:
(1)修改CommentService
@Autowired
MongoTemplate mongoTemplate;
/**
* 点赞数+1
* @param id
*/
public void updateCommentLikenum(String id){
//查询对象
Query query= Query.query(Criteria.where("_id").is(id));
//更新对象
Update update=new Update();
//局部更新,相当于$set: update.set(key,value)
//递增$inc: update.inc("likenum",1);
update.inc("likenum");
//参数1:查询对象
//参数2:更新对象
//参数3:集合的名字或实体类的类型Comment.class
mongoTemplate.updateFirst(query,update,"comment");
}
(2)测试
@Test
public void testUpdateCommentLikenum(){
//对3号文档的点赞数+1
System.out.println("修改之前的数据:");
System.out.println(commentService.findCommentById("3").getLikenum());
commentService.updateCommentLikenum("3");
System.out.println("修改之后的数据:");
System.out.println(commentService.findCommentById("3").getLikenum());
}
运行结果