在SpringBoot项目中集成MongoDB

news/2024/11/24 4:09:06/

文章目录

  • 1. 准备工作
  • 2. 在SpringBoot项目中集成MongoDB
    • 2.1 引入依赖
    • 2.2 编写配置文件
    • 2.3 实体类
  • 3. 测试
  • 4. 文档操作
    • 4.1 插入操作
      • 4.1.1 单次插入
      • 4.1.2 批量插入
    • 4.2 查询操作
      • 4.2.1 根据id查询
      • 4.2.2 根据特定条件查询
      • 4.2.3 正则查询
      • 4.2.4 查询所有文档
      • 4.2.5 排序后返回
    • 4.3 删除操作
      • 4.3.1 根据id删除
      • 4.3.2 根据特定条件删除
    • 4.4 修改操作
      • 4.4.1 修改符合条件的第一条文档(updateFirst)
      • 4.4.2 修改符合条件的所有文档(updateMulti)
  • 5. 完整的测试代码

阅读本文前可以先阅读以下文章:

  • MongoDB快速入门(MongoDB简介、MongoDB的应用场景、MongoDB中的基本概念、MongoDB的数据类型、MongoDB的安装与部署、MongoDB的常用命令)
  • MongoDB的常用命令(数据库操作、集合操作、文档操作)

1. 准备工作

假设我们在做一个与自媒体相关的项目,项目引入了 MongoDB 存储与文章的评论数据

数据库名称为 article,集合名称为 comment,以下是可能用到的字段

字段名称字段含义字段类型备注
_idIDObjectId或StringMongoDB文档的唯一标识符,作为主键使用
article_id文章IDString文章的唯一标识符,用于关联评论和文章
content评论内容String用户发表的评论文本内容
user_id评论人IDString发表评论的用户唯一标识符
nickname评论人昵称String发表评论的用户昵称,用于显示在评论列表中
create_time评论的日期时间Date评论创建的时间,格式通常为ISO日期时间格式
like_number点赞数Int32评论获得的点赞数量,反映评论的受欢迎程度
reply_number回复数Int32评论下方的回复数量,反映评论的互动程度
state状态String评论的可见状态,'0’表示评论不可见,'1’表示评论可见
parent_id上级IDString评论的上级评论ID,如果为’0’或空,则表示该评论是顶级评论,没有上级评论

先创建一个名为 article 的数据库

use comment

接着运行以下 SQL,插入测试数据

/*Navicat Premium Data TransferSource Server         : localhostSource Server Type    : MongoDBSource Server Version : 80003 (8.0.3)Source Host           : localhost:27017Source Schema         : testTarget Server Type    : MongoDBTarget Server Version : 80003 (8.0.3)File Encoding         : 65001*/// ----------------------------
// Collection structure for comment
// ----------------------------
db.getCollection("comment").drop();
db.createCollection("comment");
db.getCollection("comment").createIndex({user_id: NumberInt("1")
}, {name: "user_id_1"
});// ----------------------------
// Documents of comment
// ----------------------------
db.getCollection("comment").insertOne({_id: ObjectId("6728a523d9496fae23c4c2a9"),article_id: NumberInt("100000"),content: "今天天气真好,阳光明媚",user_id: "1001",nickname: "Rose",create_time: ISODate("2024-11-04T10:42:43.056Z"),like_number: NumberInt("10"),state: null
});db.getCollection("comment").insertOne({_id: "2",article_id: "100001",content: "我夏天空腹喝凉开水,冬天喝温开水",user_id: "1005",nickname: "伊人憔悴",create_time: ISODate("2019-08-05T23:58:51.485Z"),like_number: NumberInt("2422"),state: "1"
});db.getCollection("comment").insertOne({_id: "3",article_id: "100001",content: "我一直喝凉开水,冬天夏天都喝。",user_id: "1004",nickname: "杰克船长",create_time: ISODate("2019-08-06T01:05:06.321Z"),like_number: NumberInt("667"),state: "1"
});db.getCollection("comment").insertOne({_id: "4",article_id: "100001",content: "专家说不能空腹吃饭,影响健康。",user_id: "1003",nickname: "凯撒大帝",create_time: ISODate("2019-08-06T08:18:35.288Z"),like_number: NumberInt("2000"),state: "1"
});db.getCollection("comment").insertOne({_id: "5",article_id: "100001",content: "研究表明,刚烧开的水千万不能喝,因为烫嘴。",user_id: "1003",nickname: "凯撒大帝",create_time: ISODate("2019-08-06T11:01:02.521Z"),like_number: NumberInt("3000"),state: "1"
});

2. 在SpringBoot项目中集成MongoDB

本次演示使用的环境为:JDK 17.0.7 + SpringBoot 3.0.2

2.1 引入依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2.2 编写配置文件

application.yml

server:port: 11006spring:data:mongodb:database: articlehost: 127.0.0.1port: 27017
#      username:
#      password:

2.3 实体类

  • 在Spring Data MongoDB中,@Field注解用于指定文档中字段的名称,这在字段名称与MongoDB集合中存储的字段名称不一致时非常有用
  • 如果实体类的字段名称与MongoDB文档中的字段名称相同,那么不需要使用@Field注解
  • 通过 @Document 注解指定集合名称
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import org.springframework.data.mongodb.core.mapping.Field;import java.util.Date;/*** Comment 实体类,用于映射MongoDB中的 comment 集合。*/
@Document(collection = "comment")
public class Comment {/*** MongoDB文档的唯一标识符,作为主键使用。*/@Idprivate String id;/*** 文章的唯一标识符,用于关联评论和文章。*/@Field("article_id")private String articleId;/*** 用户发表的评论文本内容。*/private String content;/*** 发表评论的用户唯一标识符。*/@Field("user_id")private String userId;/*** 发表评论的用户昵称,用于显示在评论列表中。*/private String nickname;/*** 评论创建的时间,格式通常为ISO日期时间格式。*/@Field("create_time")private Date createTime;/*** 评论获得的点赞数量,反映评论的受欢迎程度。*/@Field("like_number")private Integer likeNumber;/*** 评论下方的回复数量,反映评论的互动程度。*/@Field("reply_number")private Integer replyNumber;/*** 评论的可见状态,'0’表示评论不可见,'1’表示评论可见。*/private String state;/*** 评论的上级评论ID,如果为’0’或空,则表示该评论是顶级评论,没有上级评论。*/@Field("parent_id")private String parentId;public String getId() {return id;}public void setId(String id) {this.id = id;}public String getArticleId() {return articleId;}public void setArticleId(String articleId) {this.articleId = articleId;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}public String getUserId() {return userId;}public void setUserId(String userId) {this.userId = userId;}public String getNickname() {return nickname;}public void setNickname(String nickname) {this.nickname = nickname;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Integer getLikeNumber() {return likeNumber;}public void setLikeNumber(Integer likeNumber) {this.likeNumber = likeNumber;}public Integer getReplyNumber() {return replyNumber;}public void setReplyNumber(Integer replyNumber) {this.replyNumber = replyNumber;}public String getState() {return state;}public void setState(String state) {this.state = state;}public String getParentId() {return parentId;}public void setParentId(String parentId) {this.parentId = parentId;}@Overridepublic String toString() {return "Comment{" +"id='" + id + '\'' +", articleId='" + articleId + '\'' +", content='" + content + '\'' +", userId='" + userId + '\'' +", nickname='" + nickname + '\'' +", createTime=" + createTime +", likeNumber=" + likeNumber +", replyNumber=" + replyNumber +", state='" + state + '\'' +", parentId='" + parentId + '\'' +'}';}}

3. 测试

  • 在 SpringBoot 中操作 MongoDB,可以使用 MongoRepository 对象,也可以使用 MongoTemplate 对象
  • MongoRepository是基于 Spring Data 的 Repository 抽象,它提供了一套标准的数据访问方法,使得 CRUD 操作变得非常简单
  • 如果需要进行复杂的查询或需要细粒度的控制,MongoTemplate 可能是更好的选择

我们编写一个测试类,在测试类中注入 MongoTemplate 对象(与使用 RedisTemplate 类似)

import com.mongodb.client.MongoDatabase;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.mongodb.core.MongoTemplate;@SpringBootTest
class MongodbApplicationTests {@Autowiredprivate MongoTemplate mongoTemplate;@Testpublic void showCurrentDatabase() {MongoDatabase db = mongoTemplate.getDb();System.out.println("db.getName() = " + db.getName());}@Testpublic void showAllCollections() {mongoTemplate.getCollectionNames().forEach(System.out::println);}}

4. 文档操作

4.1 插入操作

4.1.1 单次插入

@Test
public void testInsert() {Comment comment = new Comment();comment.setArticleId("article123");comment.setContent("这是一个很好的文章!");comment.setUserId("1003");comment.setNickname("评论者A");comment.setCreateTime(new Date());comment.setLikeNumber(10);comment.setReplyNumber(2);comment.setState("1");comment.setParentId("0");mongoTemplate.insert(comment);// 拿到插入后的评论IDSystem.out.println("tempComment.getId() = " + comment.getId());
}

4.1.2 批量插入

@Test
public void testInsertAll() {List<Comment> commentList = new ArrayList<>();for (int i = 0; i < 5; i++) {Comment comment = new Comment();comment.setArticleId("article" + (i + 1));comment.setContent("这是第 " + (i + 1) + " 条评论内容");comment.setUserId(String.valueOf(1003));comment.setNickname("评论者" + (i + 1));comment.setCreateTime(new Date());comment.setLikeNumber(5 + i); // 假设点赞数从5开始递增comment.setReplyNumber(0); // 假设初始回复数为0comment.setState("1"); // 假设所有评论都是可见的comment.setParentId("0"); // 假设所有评论都是顶级评论commentList.add(comment);}// 批量插入评论mongoTemplate.insertAll(commentList);
}

4.2 查询操作

分页参数和跳过多少条文档需要通过 Query 对象指定

4.2.1 根据id查询

@Test
public void testFindById() {Comment comment = mongoTemplate.findById("2", Comment.class);System.out.println("comment = " + comment);
}

4.2.2 根据特定条件查询

@Test
public void testFindByUserIdAndCreateTime() {String userId = "1003";Query query = new Query();Criteria criteria = Criteria.where("user_id").is(userId).and("create_time").lte(new Date());query.addCriteria(criteria).skip(0).limit(5);List<Comment> commentList = mongoTemplate.find(query, Comment.class);commentList.forEach(System.out::println);
}

4.2.3 正则查询

@Test
public void testFindByRegex() {String keyword = "开水";Query query = new Query();Criteria criteria = Criteria.where("content").regex(keyword);query.addCriteria(criteria);List<Comment> commentList = mongoTemplate.find(query, Comment.class);commentList.forEach(System.out::println);
}

4.2.4 查询所有文档

@Test
public void testFindALl() {List<Comment> commentList = mongoTemplate.findAll(Comment.class);commentList.forEach(System.out::println);
}

4.2.5 排序后返回

在这里插入图片描述

@Test
public void testFindByArticleIdWithCreatedTimeAsc() {String articleId = "100001";Criteria criteria = Criteria.where("article_id").is(articleId).and("create_time").lte(new Date());Query query = new Query();query.addCriteria(criteria).with(Sort.by(Sort.Order.asc("create_time")));List<Comment> commentList = mongoTemplate.find(query, Comment.class);commentList.forEach(System.out::println);
}

4.3 删除操作

4.3.1 根据id删除

@Test
public void testDeleteById() {Criteria criteria = Criteria.where("_id").is("2");DeleteResult deleteResult = mongoTemplate.remove(new Query(criteria), Comment.class);System.out.println("deleteResult.getDeletedCount() = " + deleteResult.getDeletedCount());
}

4.3.2 根据特定条件删除

@Test
public void testDeleteByUserIdAndCreateTime() {String userId = "1003";Date date = new Date();// 删除两分钟以内发布的评论date.setTime(date.getTime() - 2 * 60 * 1000);Query query = new Query();Criteria criteria = Criteria.where("user_id").is(userId).and("create_time").gte(date).lte(new Date()).and("state").is("1");query.addCriteria(criteria);DeleteResult deleteResult = mongoTemplate.remove(query, Comment.class);System.out.println("deleteResult.getDeletedCount() = " + deleteResult.getDeletedCount());
}

4.4 修改操作

4.4.1 修改符合条件的第一条文档(updateFirst)

@Test
public void testUpdateFirst() {Comment comment = new Comment();comment.setId("6728a523d9496fae23c4c2a9");comment.setLikeNumber(102);Query query = new Query();query.addCriteria(Criteria.where("_id").is(comment.getId()));Update update = new Update();update.set("like_number", comment.getLikeNumber());UpdateResult updateResult = mongoTemplate.updateFirst(query, update, Comment.class);System.out.println("updateResult.getMatchedCount() = " + updateResult.getMatchedCount());System.out.println("updateResult.getModifiedCount() = " + updateResult.getModifiedCount());
}

4.4.2 修改符合条件的所有文档(updateMulti)

@Test
public void testUpdateMulti() {Query query = new Query();Criteria criteria = Criteria.where("article_id").is("100001").and("state").is("1");query.addCriteria(criteria);Update update = new Update();update.set("nickname", "聂可以");UpdateResult updateResult = mongoTemplate.updateMulti(query, update, Comment.class);System.out.println("updateResult.getMatchedCount() = " + updateResult.getMatchedCount());System.out.println("updateResult.getModifiedCount() = " + updateResult.getModifiedCount());
}

5. 完整的测试代码

import cn.edu.scau.pojo.Comment;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Sort;
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;import java.util.ArrayList;
import java.util.Date;
import java.util.List;@SpringBootTest
class MongodbApplicationTests {@Autowiredprivate MongoTemplate mongoTemplate;@Testpublic void showCurrentDatabase() {MongoDatabase db = mongoTemplate.getDb();System.out.println("db.getName() = " + db.getName());}@Testpublic void showAllCollections() {mongoTemplate.getCollectionNames().forEach(System.out::println);}@Testpublic void testInsert() {Comment comment = new Comment();comment.setArticleId("article123");comment.setContent("这是一个很好的文章!");comment.setUserId("1003");comment.setNickname("评论者A");comment.setCreateTime(new Date());comment.setLikeNumber(10);comment.setReplyNumber(2);comment.setState("1");comment.setParentId("0");mongoTemplate.insert(comment);// 拿到插入后的评论IDSystem.out.println("tempComment.getId() = " + comment.getId());}@Testpublic void testInsertAll() {List<Comment> commentList = new ArrayList<>();for (int i = 0; i < 5; i++) {Comment comment = new Comment();comment.setArticleId("article" + (i + 1));comment.setContent("这是第 " + (i + 1) + " 条评论内容");comment.setUserId(String.valueOf(1003));comment.setNickname("评论者" + (i + 1));comment.setCreateTime(new Date());comment.setLikeNumber(5 + i); // 假设点赞数从5开始递增comment.setReplyNumber(0); // 假设初始回复数为0comment.setState("1"); // 假设所有评论都是可见的comment.setParentId("0"); // 假设所有评论都是顶级评论commentList.add(comment);}// 批量插入评论mongoTemplate.insertAll(commentList);}@Testpublic void testFindById() {Comment comment = mongoTemplate.findById("2", Comment.class);System.out.println("comment = " + comment);}@Testpublic void testFindALl() {List<Comment> commentList = mongoTemplate.findAll(Comment.class);commentList.forEach(System.out::println);}@Testpublic void testFindByRegex() {String keyword = "开水";Query query = new Query();Criteria criteria = Criteria.where("content").regex(keyword);query.addCriteria(criteria);List<Comment> commentList = mongoTemplate.find(query, Comment.class);commentList.forEach(System.out::println);}@Testpublic void testFindByUserIdAndCreateTime() {String userId = "1003";Query query = new Query();Criteria criteria = Criteria.where("user_id").is(userId).and("create_time").lte(new Date());query.addCriteria(criteria).skip(0).limit(5);List<Comment> commentList = mongoTemplate.find(query, Comment.class);commentList.forEach(System.out::println);}@Testpublic void testFindByArticleIdWithCreatedTimeAsc() {String articleId = "100001";Criteria criteria = Criteria.where("article_id").is(articleId).and("create_time").lte(new Date());Query query = new Query();query.addCriteria(criteria).with(Sort.by(Sort.Order.asc("create_time")));List<Comment> commentList = mongoTemplate.find(query, Comment.class);commentList.forEach(System.out::println);}@Testpublic void testDeleteById() {Criteria criteria = Criteria.where("_id").is("672a88601f90870e2451905a");DeleteResult deleteResult = mongoTemplate.remove(new Query(criteria), Comment.class);System.out.println("deleteResult.getDeletedCount() = " + deleteResult.getDeletedCount());}@Testpublic void testDeleteByUserIdAndCreateTime() {String userId = "1003";Date date = new Date();// 删除两分钟以内发布的评论date.setTime(date.getTime() - 2 * 60 * 1000);Query query = new Query();Criteria criteria = Criteria.where("user_id").is(userId).and("create_time").gte(date).lte(new Date()).and("state").is("1");query.addCriteria(criteria);DeleteResult deleteResult = mongoTemplate.remove(query, Comment.class);System.out.println("deleteResult.getDeletedCount() = " + deleteResult.getDeletedCount());}@Testpublic void testUpdateFirst() {Comment comment = new Comment();comment.setId("6728a523d9496fae23c4c2a9");comment.setLikeNumber(102);Query query = new Query();query.addCriteria(Criteria.where("_id").is(comment.getId()));Update update = new Update();update.set("like_number", comment.getLikeNumber());UpdateResult updateResult = mongoTemplate.updateFirst(query, update, Comment.class);System.out.println("updateResult.getMatchedCount() = " + updateResult.getMatchedCount());System.out.println("updateResult.getModifiedCount() = " + updateResult.getModifiedCount());}@Testpublic void testUpdateMulti() {Query query = new Query();Criteria criteria = Criteria.where("article_id").is("100001").and("state").is("1");query.addCriteria(criteria);Update update = new Update();update.set("nickname", "聂可以");UpdateResult updateResult = mongoTemplate.updateMulti(query, update, Comment.class);System.out.println("updateResult.getMatchedCount() = " + updateResult.getMatchedCount());System.out.println("updateResult.getModifiedCount() = " + updateResult.getModifiedCount());}}

http://www.ppmy.cn/news/1549442.html

相关文章

【技术开发】接口管理平台要用什么技术栈?推荐:Java+Vue3+Docker+MySQL

技术栈 【后端】Java&#xff0c;基于Spring Boot 3 MySQL Redis RabbitMQ Nacos Docker部署 【前端】基于vue3 typescript5.x element-plus2.8.x unocss0.5.x 访问管理后台&#xff08;演示环境&#xff09; 管理后台的地址是&#xff1a; http://java.test.yesapi.c…

Easyexcel(6-单元格合并)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09;Easyexcel&#xff08;4-模板文件&#xff09;Easyexcel&#xff08;5-自定义列宽&#xff09;Easyexcel&#xff08;6-单…

智能文档处理百宝箱,文档处理的必备利器

1、引言 文档解析是开发者在业务实践中会频繁面临的场景&#xff0c;不管是用AI辅助日常工作&#xff0c;还是从事产品研发&#xff0c;从非结构化文本中提取文字、图片等信息具有很大的挑战。 目前市面上的文档解析工具普遍存在繁杂无序&#xff0c;缺乏统一评估标准&#xff…

【实操之 图像处理与百度api-python版本】

1 cgg带你建个工程 如图 不然你的pip baidu-aip 用不了 先对图片进行一点处理 $ 灰度处理 $ 滤波处理 参考 import cv2 import os def preprocess_images(input_folder, output_folder):# 确保输出文件夹存在if not os.path.exists(output_folder):os.makedirs(output_fol…

JavaScript 中使用 POST 获取数据全解析

在 JavaScript 开发中&#xff0c;经常需要与服务器进行数据交互&#xff0c;而使用 POST 方法获取数据是其中重要的一环。本文将详细介绍在 JavaScript 中使用 POST 获取数据的多种方式及其相关要点&#xff0c;包括错误处理、实际应用场景以及优化和安全性等方面。 一、POST…

【Qt】QComboBox设置默认显示为空

需求 使用QComboBox&#xff0c;遇到一个小需求是&#xff0c;想要设置未点击出下拉列表时&#xff0c;内容显示为空。并且不想在下拉列表中添加一个空条目。 实现 使用setPlaceholderText()接口。我们先来看下帮助文档&#xff1a; 这里说的是&#xff0c;placeholderText是…

MySQL中索引全详解

第一部分&#xff1a;什么是索引 索引在数据库中就像书的目录&#xff0c;能够快速定位数据位置&#xff0c;从而提升查询效率。没有索引时&#xff0c;数据库查询需要从头到尾扫描整个表&#xff08;称为全表扫描&#xff09;&#xff0c;这在数据量大时非常耗时。有了索引后&…

如何更改手机GPS定位

你是否曾想过更改手机GPS位置以保护隐私、玩游戏或访问受地理限制的内容&#xff1f;接下来我将向你展示如何使用 MagFone Location Changer 更改手机GPS 位置&#xff01;无论是在玩Pokmon GO游戏、发布社媒贴子&#xff0c;这种方法都快速、简单且有效。 第一步&#xff1a;下…