当前位置: 首页 > article >正文

在SpringBoot项目中集成MongoDB

文章目录

  • 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 Transfer

 Source Server         : localhost
 Source Server Type    : MongoDB
 Source Server Version : 80003 (8.0.3)
 Source Host           : localhost:27017
 Source Schema         : test

 Target Server Type    : MongoDB
 Target 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: 11006

spring:
  data:
    mongodb:
      database: article
      host: 127.0.0.1
      port: 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文档的唯一标识符,作为主键使用。
     */
    @Id
    private 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;
    }

    @Override
    public 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 {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Test
    public void showCurrentDatabase() {
        MongoDatabase db = mongoTemplate.getDb();
        System.out.println("db.getName() = " + db.getName());
    }

    @Test
    public 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);
    // 拿到插入后的评论ID
    System.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); // 假设初始回复数为0
        comment.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 {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Test
    public void showCurrentDatabase() {
        MongoDatabase db = mongoTemplate.getDb();
        System.out.println("db.getName() = " + db.getName());
    }

    @Test
    public void showAllCollections() {
        mongoTemplate.getCollectionNames().forEach(System.out::println);
    }

    @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);
        // 拿到插入后的评论ID
        System.out.println("tempComment.getId() = " + comment.getId());
    }

    @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); // 假设初始回复数为0
            comment.setState("1"); // 假设所有评论都是可见的
            comment.setParentId("0"); // 假设所有评论都是顶级评论

            commentList.add(comment);
        }

        // 批量插入评论
        mongoTemplate.insertAll(commentList);
    }


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

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

    @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);
    }

    @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);
    }

    @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);
    }

    @Test
    public 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());
    }

    @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());
    }

    @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());
    }

    @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());
    }

}

http://www.kler.cn/a/406621.html

相关文章:

  • SHELL笔记(循环)
  • PHP实现选择排序
  • 百度主动推送可以提升抓取,它能提升索引量吗?
  • 【Redis】基于Redis实现秒杀功能
  • Go语言进阶依赖管理
  • 学习日志015--python单链表
  • 测评部署和管理 WordPress 最方便的面板
  • Sqlsugar Oracle 配置 和服务注册以及使用
  • 图文详解Docker下配置、测试Redis
  • 前端高能组件库 Shadcn-UI
  • Chroma致茂Chroma61815回收式电网模拟电源
  • SQL 分页查询详解
  • [表达式]七个古墓
  • leetcode 919.完全二叉树插入器
  • MacOS通过X11转发远程运行virt-manager进行虚机分配
  • 笔记记录 k8s-install
  • Ubuntu文件系统简记
  • 如何删除Kafka中的数据以及删除topic
  • aws配置飞书告警通知
  • Elasticsearch面试内容整理-高级特性
  • 基于Redis实现的手机短信登入功能
  • Android开发实战班 - 现代 UI 开发之 Modifier 全面应用
  • HarmonyOS笔记5:ArkUI框架的Navigation导航组件
  • 第 21 章 - Go lang反射机制
  • (python)unittest框架
  • 《线性代数的本质》