目录
2.2、创建Spring Boot工程 项目名"article"
一、MongoDB项目实战
1、MongoDB技术
1.1、mongodb-driver
mongodb-driver是mongo官方推出的java连接mongoDB的驱动包,相当于JDBC驱动.
1.2、SpringDataMongoDB
SpringData家族成员之一,用于操作MongDB的持久层框架,封装了底层的mongodb-driver。
2、项目实战
2.1、项目介绍
文章评论的项目
需求:某网站中的文章评论。评论下还有子评论等。
需要实现以下功能:
1、基本增删改查API
2、根据文章ID查询评论
3、评论点赞
表结构分析
数据库:articledb
文章评论集合:comment
字段名称 | 字段含义 | 字段类型 | 备注 |
_id | ID | ObjectId或String | MongoDB的主键的字段 |
articleid | 文章ID | String | |
content | 评论内容 | String | |
userid | 评论人ID | String | |
nickname | 评论人昵称 | String | |
createddatetime | 评论的日期时间 | Date | |
likenum | 点赞数 | Int32 | |
replnum | 回复数 | Int32 | |
state | 状态 | String | 0:不可见;1:可见; |
parentid | 上级ID | String | 如果为0表示文章的顶级评论 |
1、mongdb数据创建一条
db.comment.insert({_id:'1',content:'我相信是金子,总会有闪光之时。',publishtime:ISODate("20221022 10:10:10"),
userid:'SHK001',nickname:'悟空',createdatetime:ISODate("20221022 20:20:20"),likenum:100,
replynum:200,state:'good',parentid:'wwk334',articleid:'QW987'});
2.2、创建Spring Boot工程 项目名"article"
创建Spring Boot 工程Spring Boot入门+深入(一)
1、pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>article</groupId>
<artifactId>article</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>article</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven-jar-plugin.version>3.0.0</maven-jar-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
2、application.yml
spring:
#数据源配置
data:
mongodb:
#主机地址
host: 192.168.0.125
#数据源
database: articledb
#也可以使用uri连接
#uri: mongodb://192.168.0.125:27017/articledb
#默认端口是27017
port: 27017
username: admin
password: admin
3、项目启动类
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringMainApplication {
public static void main(String[] args) {
SpringApplication.run(SpringMainApplication.class,args);
}
}
上述配置完成,直接启动项目
...
2022-10-22 22:40:46.556 INFO 9032 --- [168.0.125:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1}] to 192.168.0.125:27017
2022-10-22 22:40:46.562 INFO 9032 --- [168.0.125:27017] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=192.168.0.125:27017, type=STANDALONE, state=CONNECTED, ok=true, version=ServerVersion{versionList=[6, 0, 2]}, minWireVersion=0, maxWireVersion=17, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=4659100}
2022-10-22 22:40:46.757 INFO 9032 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2022-10-22 22:40:46.761 INFO 9032 --- [ main] com.lwz.SpringMainApplication : Started SpringMainApplication in 5.824 seconds (JVM running for 6.232)
控制台没有报错,代表启动成功。
2.3、项目代码编写
创建实体类
创建包com.lwz.article,包下建包entity用于存放实体类,创建实体类
Comment.java
package com.lwz.article.entity;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;
import lombok.Data;
@Data
@Document(collection = "comment")//可以省略,如果省略默认使用类名小写映射集合
//@CompoundIndex(def = "{'userid':1,'nickname':-1}") //复合索引
public class Comment implements Serializable{
private static final long serialVersionUID = 1L;
@Id
private String id;//主键
@Field("content")//该属性对应mongdb中的字段名/实体类名称和db中的名称不一致时使用
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;
@Override
public String toString() {
return "Comment [id=" + id + ", content=" + content + ", publishtime=" + publishtime + ", userid=" + userid
+ ", nickname=" + nickname + ", createdatetime=" + createdatetime + ", likenum=" + likenum
+ ", replynum=" + replynum + ", state=" + state + ", parentid=" + parentid + ", articleid=" + articleid
+ "]";
}
}
CommentRepository.java
package com.lwz.article.repository;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.lwz.article.entity.Comment;
public interface CommentRepository extends MongoRepository<Comment,String>{
}
CommentService ---文章评论的增删改查
package com.lwz.article.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.lwz.article.entity.Comment;
import com.lwz.article.repository.CommentRepository;
@Service
public class CommentService {
@Autowired
private CommentRepository commentRepository;
/**
* 保存评论
*/
public void saveComment(Comment comment) {
commentRepository.save(comment);
}
/**
* 更新评论
*/
public void updateComment(Comment comment) {
commentRepository.save(comment);
}
/**
* 根据ID删除评论
*/
public void deleteCommentById(String id) {
commentRepository.deleteById(id);
}
/**
* 查询所有评论
*/
public List<Comment> findCommentList() {
return commentRepository.findAll();
}
/**
* 根据ID查询评论
*/
public Comment findCommentById(String id) {
return commentRepository.findById(id).get();
}
}
CommentServiceTest测试类
package com.lwz.article.service;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.lwz.article.entity.Comment;
@RunWith(SpringRunner.class)
@SpringBootTest
public class CommentServiceTest {
@Autowired
private CommentService commentService;
@Test
public void findCommentListTest() {
List<Comment> commentList = commentService.findCommentList();
System.out.println(commentList);
}
}
启动测试类进行测试:
错误1:
Caused by: com.mongodb.MongoCommandException: Command failed with error 18 (AuthenticationFailed): 'Authentication failed.' on server 192.168.0.125:27017. The full response is { "ok" : 0.0, "errmsg" : "Authentication failed.", "code" : 18, "codeName" : "AuthenticationFailed" }
at com.mongodb.internal.connection.ProtocolHelper.getCommandFailureException(ProtocolHelper.java:179)
解决方式:
MongoDB中每个数据库之间是相互独立的,都有独立的权限,正确的做法是使用root账号在【将要操作的数据库】中创建一个【子账号】,在用这个子账号连接mongo:
>use articledb
switched to db articledb
> db.createUser({user:"admin",pwd:"admin",roles:[{role:"dbOwner",db:"articledb"}]})
...
错误2:
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [java.util.Date] for value '2022-10-22'; nested exception is java.lang.IllegalArgumentException
at org.springframework.core.convert.support.ObjectToObjectConverter.convert(ObjectToObjectConverter.java:112)
解决方式:
实体类Date类型和数据库中数据格式,创建mongdb时间数据使用ISODate函数
db.comment.insert({_id:'1',content:'我相信是金子,总会有闪光之时。',publishtime:ISODate("20221022 10:10:10"),
userid:'SHK001',nickname:'悟空',createdatetime:ISODate("20221022 20:20:20"),likenum:100,
replynum:200,state:'good',parentid:'wwk334',articleid:'QW987'});
问题解决后,再次启动测试类,成功!
控制台会打印如下结果:
[Comment [id=1, content=我相信是金子,总会有闪光之时。, publishtime=Sat Oct 22 18:10:10 CST 2022, userid=SHK001, nickname=悟空, createdatetime=2022-10-23T04:20:20, likenum=100, replynum=200, state=good, parentid=wwk334, articleid=QW987]]
2.3.1、分页查询功能
根据上级id查询文章评论的分页列表。
(1)、CommentRepository.java新增方法
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.repository.MongoRepository;
import com.lwz.article.entity.Comment;
public interface CommentRepository extends MongoRepository<Comment,String>{
Page<Comment> findByParentid(String parentid,Pageable pageable);
}
(2)、CommentService新增方法
/**
* 根据上级id分页查询
*/
public Page<Comment> findCommentListByParentid(String parentid,int page,int size) {
return commentRepository.findByParentid(parentid,PageRequest.of(page-1, size));
}
(3)、CommentServiceTest测试类新增测试方法
@Test
public void findCommentListByParentidTest() {
Page<Comment> page = commentService.findCommentListByParentid("wwk334",1,2);
System.out.println(page.getTotalElements());
System.out.println(page.getContent());
}
执行测试类:结果
1
[Comment [id=1, content=我相信是金子,总会有闪光之时。, publishtime=Sat Oct 22 18:10:10 CST 2022, userid=SHK001, nickname=悟空, createdatetime=2022-10-23T04:20:20, likenum=100, replynum=200, state=good, parentid=wwk334, articleid=QW987]]
2.3.2、实现评论点赞
方法1:
/**
* 更新点赞数
*/
public void updateCommentLikenumById(String id) {
Comment comment = commentRepository.findById(id).get();
comment.setLikenum(comment.getLikenum()+1);
commentRepository.save(comment);
}
方法2:
我们可以使用MongoTemplate类来实现对某列的操作。
(1)、修改CommentService
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
--------------------------------------------------------
@Autowired
private MongoTemplate mongoTemplate;
/**
* 更新点赞数
*/
public void updateCommentLikenum(String id) {
//查询条件
Query query = Query.query(Criteria.where("_id").is(id));
//更新条件
Update update = new Update();
update.inc("likenum");
mongoTemplate.updateFirst(query, update, Comment.class);
}
(2)、CommentServiceTest测试类新增测试方法
@Test
public void updateCommentLikenum() {
Comment comment = commentService.findCommentById("1");
System.out.println(comment.getLikenum());
commentService.updateCommentLikenum("1");
Comment comment1 = commentService.findCommentById("1");
System.out.println(comment1.getLikenum());
}
测试结果:
100
101
3、Java MongDb去重
MongoCollection<Document> collection = database.getCollection("collectionName");
List<String> uniqueValues = collection.distinct("fieldName", String.class).into(new ArrayList<>());
4、查询条件
Document doc = new Document();
doc.put("age",new Document("$gte",18));
doc.put("age",new Document("$lte",30));
5、查询 MongDb某个字段重复
db.getCollection("xx_table").aggregate([
{ $group: { _id : '$class_name', count: { $sum : 1 } } },
{ $match: { count: { $gt : 1} } }
])
每天⽤⼼记录⼀点点。内容也许不重要,但习惯很重要!
干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天!