MongoDB整合SpringBoot

news2024/12/29 8:44:49

MongoDB整合SpringBoot

环境准备

1.引入依赖

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

2.配置yml

spring:
  data:
    mongodb:
      uri: mongodb://fox:fox@192.168.65.174:27017/test?authSource=admin
      #uri等同于下面的配置
      #database: test
      #host: 192.168.65.174
      #port: 27017
      #username: fox
      #password: fox
      #authentication-database: admin

连接配置参考文档:https://www.mongodb.com/zh-cn/docs/manual/reference/connection-string/

3.使用时注入mongoTemplate

@Autowired

MongoTemplate mongoTemplate;

集合操作

@Test

public void testCollection(){

    boolean exists = mongoTemplate.collectionExists("emp");

    if (exists) {

        //删除集合

        mongoTemplate.dropCollection("emp");

    }

    //创建集合

    mongoTemplate.createCollection("emp");

}

文档操作

相关注解

  • @Document
    • 修饰范围: 用在类上
    • 作用: 用来映射这个类的一个对象为mongo中一条文档数据。
    • 属性:( value 、collection )用来指定操作的集合名称
  • @Id
    • 修饰范围: 用在成员变量、方法上
    • 作用: 用来将成员变量的值映射为文档的_id的值
  • @Field
    • 修饰范围: 用在成员变量、方法上
    • 作用: 用来将成员变量及其值映射为文档中一个key:value对。
    • 属性:( name , value )用来指定在文档中 key的名称,默认为成员变量名
  • @Transient
    • 修饰范围:用在成员变量、方法上
    • 作用:用来指定此成员变量不参与文档的序列化

创建实体

@Document("emp")  //对应emp集合中的一个文档

@Data

@AllArgsConstructor

@NoArgsConstructor

public class Employee {



    @Id   //映射文档中的_id

    private Integer id;

    @Field("username")

    private String name;

    @Field

    private int age;

    @Field

    private Double salary;

    @Field

    private Date birthday;

}

添加文档

insert方法返回值是新增的Document对象,里面包含了新增后_id的值。如果集合不存在会自动创建集合。通过Spring Data MongoDB还会给集合中多加一个_class的属性,存储新增时Document对应Java中类的全限定路径。这么做为了查询时能把Document转换为Java类型。

@Test

public void testInsert(){

    Employee employee = new Employee(1, "小明", 30,10000.00, new Date());

    

    //添加文档

    // sava:  _id存在时更新数据

    //mongoTemplate.save(employee);

    // insert: _id存在抛出异常   支持批量操作

    mongoTemplate.insert(employee);

    

    List<Employee> list = Arrays.asList(

            new Employee(2, "张三", 21,5000.00, new Date()),

            new Employee(3, "李四", 26,8000.00, new Date()),

            new Employee(4, "王五",22, 8000.00, new Date()),

            new Employee(5, "张龙",28, 6000.00, new Date()),

            new Employee(6, "赵虎",24, 7000.00, new Date()),

            new Employee(7, "赵六",28, 12000.00, new Date()));

    //插入多条数据

    mongoTemplate.insert(list,Employee.class);

} 
  • 插入重复数据时: insert报 DuplicateKeyException提示主键重复; save对已存在的数据进行更新。
  • 批处理操作时: insert可以一次性插入所有数据,效率较高;save需遍历所有数据,一次插入或更新,效率较低。

查询文档

Criteria是标准查询的接口,可以引用静态的Criteria.where的把多个条件组合在一起,就可以轻松地将多个方法标准和查询连接起来,方便我们操作查询语句。

@Test

public void testFind(){



    System.out.println("==========查询所有文档===========");

    //查询所有文档

    List<Employee> list = mongoTemplate.findAll(Employee.class);

    list.forEach(System.out::println);



    System.out.println("==========根据_id查询===========");

    //根据_id查询

    Employee e = mongoTemplate.findById(1, Employee.class);

    System.out.println(e);



    System.out.println("==========findOne返回第一个文档===========");

    //如果查询结果是多个,返回其中第一个文档对象

    Employee one = mongoTemplate.findOne(new Query(), Employee.class);

    System.out.println(one);



    System.out.println("==========条件查询===========");

    //new Query() 表示没有条件

    //查询薪资大于等于8000的员工

    //Query query = new Query(Criteria.where("salary").gte(8000));

    //查询薪资大于4000小于10000的员工

    //Query query = new Query(Criteria.where("salary").gt(4000).lt(10000));

    //正则查询(模糊查询)  java中正则不需要有//

    //Query query = new Query(Criteria.where("name").regex("张"));



    //and  or  多条件查询

    Criteria criteria = new Criteria();

    //and  查询年龄大于25&薪资大于8000的员工

    //criteria.andOperator(Criteria.where("age").gt(25),Criteria.where("salary").gt(8000));

    //or 查询姓名是张三或者薪资大于8000的员工

    criteria.orOperator(Criteria.where("name").is("张三"),Criteria.where("salary").gt(5000));

    Query query = new Query(criteria);



    //sort排序

    //query.with(Sort.by(Sort.Order.desc("salary")));





    //skip limit 分页  skip用于指定跳过记录数,limit则用于限定返回结果数量。

    query.with(Sort.by(Sort.Order.desc("salary")))

            .skip(0)  //指定跳过记录数

            .limit(4);  //每页显示记录数





    //查询结果

    List<Employee> employees = mongoTemplate.find(

            query, Employee.class);

    employees.forEach(System.out::println);

}
@Test

public void testFindByJson() {



    //使用json字符串方式查询

    //等值查询

    //String json = "{name:'张三'}";

    //多条件查询

    String json = "{$or:[{age:{$gt:25}},{salary:{$gte:8000}}]}";

    Query query = new BasicQuery(json);



    //查询结果

    List<Employee> employees = mongoTemplate.find(

            query, Employee.class);

    employees.forEach(System.out::println);

}

更新文档

在Mongodb中无论是使用客户端API还是使用Spring Data,更新返回结果一定是受行数影响。如果更新后的结果和更新前的结果是相同,返回0。

  • updateFirst() 只更新满足条件的第一条记录
  • updateMulti() 更新所有满足条件的记录
  • upsert() 没有符合条件的记录则插入数据
@Test

public void testUpdate(){

    //query设置查询条件

    Query query = new Query(Criteria.where("salary").gte(15000));

    System.out.println("==========更新前===========");

    List<Employee> employees = mongoTemplate.find(query, Employee.class);

    employees.forEach(System.out::println);



    Update update = new Update();

    //设置更新属性

    update.set("salary",13000);



    //updateFirst() 只更新满足条件的第一条记录

    //UpdateResult updateResult = mongoTemplate.updateFirst(query, update, Employee.class);

    //updateMulti() 更新所有满足条件的记录

    //UpdateResult updateResult = mongoTemplate.updateMulti(query, update, Employee.class);



    //upsert() 没有符合条件的记录则插入数据

    //update.setOnInsert("id",11);  //指定_id

    UpdateResult updateResult = mongoTemplate.upsert(query, update, Employee.class);



    //返回修改的记录数

    System.out.println(updateResult.getModifiedCount());





    System.out.println("==========更新后===========");

    employees = mongoTemplate.find(query, Employee.class);

    employees.forEach(System.out::println);

}

删除文档

@Test

public void testDelete(){

    //删除所有文档

    //mongoTemplate.remove(new Query(),Employee.class);

    //条件删除

    Query query = new Query(Criteria.where("salary").gte(10000));

    mongoTemplate.remove(query,Employee.class);

}

聚合操作

MongoTemplate提供了aggregate方法来实现对数据的聚合操作。

基于聚合管道mongodb提供的可操作的内容:

基于聚合操作Aggregation.group,mongodb提供可选的表达式

示例:以聚合管道示例2为例

返回人口超过1000万的州

db.zips.aggregate( [

   { $group: { _id: "$state", totalPop: { $sum: "$pop" } } },

   { $match: { totalPop: { $gt: 10*1000*1000 } } }

] )

java实现

@Test

public void test(){

    //$group

    GroupOperation groupOperation = Aggregation.group("state").sum("pop").as("totalPop");



    //$match

    MatchOperation matchOperation = Aggregation.match(

            Criteria.where("totalPop").gte(10*1000*1000));



    // 按顺序组合每一个聚合步骤

    TypedAggregation<Zips> typedAggregation = Aggregation.newAggregation(Zips.class,

             groupOperation, matchOperation);



    //执行聚合操作,如果不使用 Map,也可以使用自定义的实体类来接收数据

    AggregationResults<Map> aggregationResults = mongoTemplate.aggregate(typedAggregation, Map.class);

    // 取出最终结果

    List<Map> mappedResults = aggregationResults.getMappedResults();

    for(Map map:mappedResults){

        System.out.println(map);

    }



}

返回各州平均城市人口

db.zips.aggregate( [

   { $group: { _id: { state: "$state", city: "$city" }, cityPop: { $sum: "$pop" } } },

   { $group: { _id: "$_id.state", avgCityPop: { $avg: "$cityPop" } } },

   { $sort:{avgCityPop:-1}}

] )

java实现

@Test

public void test2(){

    //$group

    GroupOperation groupOperation = Aggregation.group("state","city").sum("pop").as("cityPop");

    //$group

    GroupOperation groupOperation2 = Aggregation.group("_id.state").avg("cityPop").as("avgCityPop");

    //$sort

    SortOperation sortOperation = Aggregation.sort(Sort.Direction.DESC,"avgCityPop");

    

    // 按顺序组合每一个聚合步骤

    TypedAggregation<Zips> typedAggregation = Aggregation.newAggregation(Zips.class,

            groupOperation, groupOperation2,sortOperation);



    //执行聚合操作,如果不使用 Map,也可以使用自定义的实体类来接收数据

    AggregationResults<Map> aggregationResults = mongoTemplate.aggregate(typedAggregation, Map.class);

    // 取出最终结果

    List<Map> mappedResults = aggregationResults.getMappedResults();

    for(Map map:mappedResults){

        System.out.println(map);

    }

}

按州返回最大和最小的城市

db.zips.aggregate( [

   { $group:

      {

        _id: { state: "$state", city: "$city" },

        pop: { $sum: "$pop" }

      }

   },

   { $sort: { pop: 1 } },

   { $group:

      {

        _id : "$_id.state",

        biggestCity:  { $last: "$_id.city" },

        biggestPop:   { $last: "$pop" },

        smallestCity: { $first: "$_id.city" },

        smallestPop:  { $first: "$pop" }

      }

   },

  { $project:

    { _id: 0,

      state: "$_id",

      biggestCity:  { name: "$biggestCity",  pop: "$biggestPop" },

      smallestCity: { name: "$smallestCity", pop: "$smallestPop" }

    }

  },

   { $sort: { state: 1 } }

] )

java实现

@Test

public void test3(){

    //$group

    GroupOperation groupOperation = Aggregation

            .group("state","city").sum("pop").as("pop");



    //$sort

    SortOperation sortOperation = Aggregation

            .sort(Sort.Direction.ASC,"pop");



    //$group

    GroupOperation groupOperation2 = Aggregation

            .group("_id.state")

            .last("_id.city").as("biggestCity")

            .last("pop").as("biggestPop")

            .first("_id.city").as("smallestCity")

            .first("pop").as("smallestPop");



    //$project

    ProjectionOperation projectionOperation = Aggregation

            .project("state","biggestCity","smallestCity")

            .and("_id").as("state")

            .andExpression(

                    "{ name: \"$biggestCity\",  pop: \"$biggestPop\" }")

            .as("biggestCity")

            .andExpression(

                    "{ name: \"$smallestCity\", pop: \"$smallestPop\" }"

            ).as("smallestCity")

            .andExclude("_id");



    //$sort

    SortOperation sortOperation2 = Aggregation

            .sort(Sort.Direction.ASC,"state");





    // 按顺序组合每一个聚合步骤

    TypedAggregation<Zips> typedAggregation = Aggregation.newAggregation(

            Zips.class, groupOperation, sortOperation, groupOperation2,

            projectionOperation,sortOperation2);



    //执行聚合操作,如果不使用 Map,也可以使用自定义的实体类来接收数据

    AggregationResults<Map> aggregationResults = mongoTemplate

            .aggregate(typedAggregation, Map.class);

    // 取出最终结果

    List<Map> mappedResults = aggregationResults.getMappedResults();

    for(Map map:mappedResults){

        System.out.println(map);

    }



}

小技巧:如何去掉_class属性

@Configuration

public class TulingMongoConfig {

    /**

     * 定制TypeMapper去掉_class属性

     * @param mongoDatabaseFactory

     * @param context

     * @param conversions

     * @return

     */

    @Bean

    MappingMongoConverter mappingMongoConverter(

            MongoDatabaseFactory mongoDatabaseFactory,

            MongoMappingContext context, MongoCustomConversions conversions){



        DbRefResolver dbRefResolver = new DefaultDbRefResolver(mongoDatabaseFactory);

        MappingMongoConverter mappingMongoConverter =

                new MappingMongoConverter(dbRefResolver,context);

        mappingMongoConverter.setCustomConversions(conversions);



        //构造DefaultMongoTypeMapper,将typeKey设置为空值

        mappingMongoConverter.setTypeMapper(new DefaultMongoTypeMapper(null));



        return mappingMongoConverter;

    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2255318.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【简洁明快】使用python读取数据建立pptx (python-pptx图文调整案例)

使用python自动读取数据建立pptx 前言如何使用 Python 自动生成 PPTX第一步&#xff1a;安装所需库第二步&#xff1a;创建一个新的 PPTX第三步&#xff1a;添加幻灯片第四步&#xff1a;添加内容添加文本添加图片第五步&#xff1a;保存 PPTX 图文实操案例&#xff08;自动读取…

三维扫描检测在汽车制造中的应用

三维扫描&#xff0c;通过先进三维扫描技术获取产品和物体的形面三维数据&#xff0c;建立实物的三维图档&#xff0c;满足各种实物3D模型数据获取、三维数字化展示、3D多媒体开发、三维数字化存档、逆向设计、产品开发、直接3D打印制造或辅助加工制造等一系列的应用。 三维扫描…

flyway执行sql遇到变量执行报错解决

前两天在公司使用flyway工具执行sql时&#xff0c;开发写的sql里面有变量&#xff0c;于是这个flyway工具不识别这个变量直接报错&#xff0c;不接着往下执行了。报错信息如下&#xff1a; flyway工具执行sql报错 information: No value provided for placeholder: ${ep1} 于是…

go语言的sdk项目搭建与git 操作标签tag并推送至远程仓库

在搭建 SDK 项目并结合 Git 操作标签&#xff08;Tag&#xff09;时&#xff0c;通常会涉及项目初始化、版本管理、Git 标签的创建与管理等内容。以下是一个完整的步骤指南&#xff0c;帮助您搭建 SDK 项目并学习如何使用 Git 标签。 ### 1. **搭建 SDK 项目** 首先&#xff…

机器学习算法的核心理论小总结

机器学习算法的核心在于利用数据构建模型以解决实际问题&#xff0c;而理解其理论基础是高效应用的关键。本文从机器学习的基本概念出发&#xff0c;详细解析监督学习中的几种经典算法&#xff0c;如逻辑回归、决策树和支持向量机&#xff08;SVM&#xff09;。同时&#xff0c…

3.STM32通信接口之SPI通信---SPI实战(W25Q64存储模块介绍)《精讲》

上一节介绍了SPI的通信过程和方法&#xff0c;接下来就要进行STM32与外围模块通信了&#xff0c;这个模块是一块非易失型存储芯片&#xff0c;能够提供8MB的存储空间。接下来跟着Whappy脚步&#xff0c;进行探索新大陆吧&#xff01;【免费】W25Q64(中英文数据手册)资源-CSDN文…

第七节(1)、T型加减速转动【51单片机-TB6600驱动器-步进电机教程】

摘要&#xff1a;本节介绍步进电机T型加减速的控制方法&#xff0c;分2个小节&#xff0c;本小节主要内容为该控制方法的推导与计算&#xff0c;第二节对T型加减速进行了简化计算 一.加速阶段计算 1.1 计算时间与步数关系 根据位移公式可得&#xff1a; a n g l e 0 n ∗ s…

Python123_Python程序语言设计基础_Python基本图形绘制

turtle八边形绘制 ‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬ 描述 使用tur…

刘铁猛p3 C# 控制台程序引用System.Windows.Forms报错,无法引用程序集 解决方法

学习刘铁猛老师c#入门详解第三集 引用System.Windows.Forms时报错了 错误图例 为什么控制台应用添加项目引用里面为什么找不到任何项目&#xff0c;同时从com里面加的引用会出现警告&#xff1f; 其实是创建控制台程序的时候出错了 解决方法 重新创建控制台程序 选控制台应…

Linux下,用ufw实现端口关闭、流量控制(二)

本文是 网安小白的端口关闭实践 的续篇。 海量报文&#xff0c;一手掌握&#xff0c;你值得拥有&#xff0c;让我们开始吧&#xff5e; ufw 与 iptables的关系 理论介绍&#xff1a; ufw&#xff08;Uncomplicated Firewall&#xff09;是一个基于iptables的前端工具&#xf…

Leetcode 每日一题 290.单词规律

目录 一、问题分析 二、解题思路 三、代码实现 四、复杂度分析 五、总结 在编程的世界里&#xff0c;我们常常会遇到各种有趣的字符串匹配问题。今天要探讨的就是这样一个问题&#xff1a;给定一种规律 pattern 和一个字符串 s&#xff0c;判断 s 是否遵循与 pattern 相同…

Java项目实战II基于微信小程序的旅游社交平台(开发文档+数据库+源码)

目录 一、前言 二、技术介绍 三、系统实现 四、核心代码 五、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 一、前言 随着移动互联网的迅猛发展&#xff0c;旅游已经成为人…

Mybatis-Plus的主要API

一、实体类操作相关API BaseMapper<T>接口 功能&#xff1a;这是 MyBatis - Plus 为每个实体类对应的 Mapper 接口提供的基础接口。它提供了一系列基本的 CRUD&#xff08;增删改查&#xff09;操作方法。例如insert(T entity)方法用于插入一条记录&#xff0c;d…

第一个 JSP 程序

一个简单的 JSP 程序&#xff1a; 使用 IDEA 开发工具新建一个 maven 项目&#xff0c;具体操作如图所示&#xff1a; 配置 Tomcat 服务器 项目结构如下图所示&#xff1a; 3. 修改 index.jsp 页面的代码&#xff1a; <% page language"java" contentType&q…

使用android studio写一个Android的远程通信软件(APP),有通讯的发送和接收消息界面

以下是使用 Android Studio 基于 Java 语言编写一个简单的 Android APP 实现远程通信&#xff08;这里以 TCP 通信为例&#xff09;的代码示例&#xff0c;包含基本的通信界面以及发送和接收消息功能。 1. 创建项目 打开 Android Studio&#xff0c;新建一个 Empty Activity …

记录下nginx接口代理配置问题

其中api和api1是前面定义的upstream&#xff0c;ip相同只是端口不同。 一开始/api1/直接 像api一样 proxy_pass http://api1这样是不行的&#xff0c;因为会代理到 后端的 /api1/...接口&#xff0c;而后端实际接口地址是 /api/..... 所以必须像上面写法才能将外网的 /api…

【项目】基于PaddleOCR的文字检测识别项目

【项目】基于PaddleOCR的文字检测识别项目 简介安装与使用&#xff08;1&#xff09;Paddle环境安装&#xff08;2&#xff09;模型预测&#xff08;文本检测文本识别&#xff09;&#xff08;3&#xff09;文本检测识别模型训练&#xff08;4&#xff09;本地模型训练与预测&a…

mock.js介绍

mock.js http://mockjs.com/ 1、mock的介绍 *** 生成随机数据&#xff0c;拦截 Ajax 请求。** 通过随机数据&#xff0c;模拟各种场景&#xff1b;不需要修改既有代码&#xff0c;就可以拦截 Ajax 请求&#xff0c;返回模拟的响应数据&#xff1b;支持生成随机的文本、数字…

重磅升级:OpenAI o1模型上手实测,从芯片架构分析到象棋残局判断的全能表现

引言 昨日&#xff0c;在圣诞节系列发布会的第一天&#xff0c;OpenAI终于给我们带来了令人振奋的更新&#xff0c;这些更新有望塑造AI互动的未来。备受期待的OpenAI o1正式版的推出&#xff0c;标志着ChatGPT体验的重大进化&#xff0c;宣告了AI驱动应用新时代的开始。o1现已可…

DataSophon集成CMAK KafkaManager

本次集成基于DDP1.2.1 集成CMAK-3.0.0.6 设计的json和tar包我放网盘了. 通过网盘分享的文件&#xff1a;DDP集成CMAK 链接: https://pan.baidu.com/s/1BR70Ajj9FxvjBlsOX4Ivhw?pwdcpmc 提取码: cpmc CMAK github上提供了zip压缩包.将压缩包解压之后 在根目录下加入启动脚本…