SpringBoot--中间件技术-3:整合mongodb,整合ElasticSearch,附案例含代码(简单易懂)

SpringBoot整合mongodb

实现步骤:

  1. pom文件导坐标

    xml 复制代码
    <!--mongo-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
    </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>
      <scope>test</scope>
    </dependency>
  2. yaml配置文件配置mongodb:

    yaml 复制代码
    spring:
      data:
        mongodb:
          uri: mongodb://localhost/spring
  3. 随便建一个pojo

    java 复制代码
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Book {
        private int id;
        private String name;
        private String type;
        private String description;
    }
  4. 测试:

    java 复制代码
    @SpringBootTest
    class SpringbootMongodb01ApplicationTests {
    
      @Autowired(required = false)
      private MongoTemplate mongoTemplate;
    
      @Test
      void contextLoads() {
        Book book = new Book();
        book.setId(4);
        book.setName("董健翔");
        book.setType("牛逼");
        book.setDescription("真牛逼");
        mongoTemplate.save(book);
      }
    
      @Test
      void find(){
        List<Book> all = mongoTemplate.findAll(Book.class);
        System.out.println(all);
      }
    }

    装配MongoTemplate模板类,调用方法

整合MongoDB总结:

  1. 导坐标
  2. 写配置文件
  3. 核心类MongoTemplate调用

SpringBoot整合ElasticSearch

前提准备:数据库+ES

数据库建表语句:

sql 复制代码
DROP TABLE IF EXISTS `tb_hotel`;
CREATE TABLE `tb_hotel`  (
  `id` bigint(20) NOT NULL COMMENT '酒店id',
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店名称',
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店地址',
  `price` int(10) NOT NULL COMMENT '酒店价格',
  `score` int(2) NOT NULL COMMENT '酒店评分',
  `brand` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '酒店品牌',
  `city` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '所在城市',
  `star_name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '酒店星级,1星到5星,1钻到5钻',
  `business` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '商圈',
  `latitude` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '纬度',
  `longitude` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '经度',
  `pic` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '酒店图片',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

实现步骤:

  1. pom文件到坐标

    xml 复制代码
    <properties>
      <!--锁定jdk版本-->
      <java.version>1.8</java.version>
      <!--锁定es版本-->
      <elasticsearch.version>7.12.0</elasticsearch.version>
    </properties>
    
    <dependencies>
      <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>
        <scope>test</scope>
      </dependency>
    
      <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
      </dependency>
    
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>3.4.2</version>
      </dependency>
      <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.29</version>
      </dependency>
      <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
      </dependency>
      <!--FastJson-->
      <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>1.2.71</version>
      </dependency>
    </dependencies>
  2. yaml配置文件

    yaml 复制代码
    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/spring?serverTimezone=GMT
        username: root
        password: 123456
    logging:
      level:
        com.dong: debug
    mybatis-plus:
      configuration:
        map-underscore-to-camel-case: true
      type-aliases-package: com.dong.pojo
  3. 创建实体类:

    对应数据库表的实体类

    java 复制代码
    @NoArgsConstructor
    @AllArgsConstructor
    @Data
    @TableName("tb_hotel")
    public class Hotel {
      @TableId(type = IdType.INPUT)
      private Long id;
      private String name;
      private String address;
      private Integer price;
      private Integer score;
      private String brand;
      private String city;
      private String starName;
      private String business;
      private String longitude;//经度
      private String latitude;//纬度
      private String pic;
    }

    对应ES的实体类

    java 复制代码
    @Data
    @NoArgsConstructor
    public class HotelDoc {
      private Long id;
      private String name;
      private String address;
      private Integer price;
      private Integer score;
      private String brand;
      private String city;
      private String starName;
      private String business;
      private String location;
      private String pic;
    // 构造方法用于类型转换   将数据库中的经、纬度用坐标location代替,所以HotelDoc稍有不同
      public HotelDoc(Hotel hotel){   
        this.id = hotel.getId();
        this.name = hotel.getName();
        this.address = hotel.getAddress();
        this.price = hotel.getPrice();
        this.score = hotel.getScore();
        this.brand = hotel.getBrand();
        this.city = hotel.getCity();
        this.starName = hotel.getStarName();
        this.business = hotel.getBusiness();
        this.location = hotel.getLatitude() + ", "+ hotel.getLongitude();
        this.pic = hotel.getPic();
      }
    }
  4. mapper层:

    java 复制代码
    @Mapper
    public interface HotelMapper extends BaseMapper<Hotel> {
    }
  5. service层:

    接口:

    java 复制代码
    public interface IHotelService extends IService<Hotel> {
    }

    实现类:

    java 复制代码
    @Service
    public class HotelServiceImp extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
    }
  6. 演示在juint中进行,演示对索引库和文档的操作

索引库的操作

  • 判断索引库是否存在(其实就是查询)
  • 创建索引库
  • 删除索引库
java 复制代码
@SpringBootTest
class SpringbootEs01ApplicationTests {
	// 操作es的核心对象
  private RestHighLevelClient client;
	// 单元测试之前都执行的,告诉核心对象es的端口号  固定语法
  @BeforeEach
  void setUp(){
    this.client = new RestHighLevelClient(RestClient.builder(
      HttpHost.create("http://localhost:9200")
    ));
  }
	// 单元测试之后都执行的
  @AfterEach
  void tearDown() throws Exception{
    this.client.close();
  }

  // 判断索引库是否存在
  @Test
  void testExistsHotelIndex() throws Exception {
    GetIndexRequest request = new GetIndexRequest("hotels");
    boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    System.err.println(exists ? "索引库已经存在":"索引库不存在");
  }

  // 创建索引库
  @Test
  void createHotelIndex() throws Exception{
    // 创建Request对象
    CreateIndexRequest request = new CreateIndexRequest("hotels");
    // 准备请求的参数:DSL语句
    request.source(HotelConstants.MAPPING_TEMPLATE, XContentType.JSON);
    // 发送请求
    client.indices().create(request,RequestOptions.DEFAULT);
  }

  // 删除索引库
  @Test
  void delteHotelIndex() throws Exception{
    // 创建Request对象
    DeleteIndexRequest request = new DeleteIndexRequest("hotels");
    // 发送请求
    client.indices().delete(request,RequestOptions.DEFAULT);
  }
}

创建索引库的时候需要映射,映射往往是一个复杂且长的JSON,所以单独写个类,上面创建索引库的映射如下

可以在postman中写好粘贴过来

java 复制代码
public class HotelConstants {
  public static final String MAPPING_TEMPLATE = "{\n" +
    "  \"mappings\": {\n" +
    "    \"properties\": {\n" +
    "      \"id\": {\n" +
    "        \"type\": \"keyword\"\n" +
    "      },\n" +
    "      \"name\":{\n" +
    "        \"type\": \"text\",\n" +
    "        \"analyzer\": \"ik_max_word\",\n" +
    "        \"copy_to\": \"all\"\n" +
    "      },\n" +
    "      \"address\":{\n" +
    "        \"type\": \"keyword\",\n" +
    "        \"index\": false\n" +
    "      },\n" +
    "      \"price\":{\n" +
    "        \"type\": \"integer\"\n" +
    "      },\n" +
    "      \"score\":{\n" +
    "        \"type\": \"integer\"\n" +
    "      },\n" +
    "      \"brand\":{\n" +
    "        \"type\": \"keyword\",\n" +
    "        \"copy_to\": \"all\"\n" +
    "      },\n" +
    "      \"city\":{\n" +
    "        \"type\": \"keyword\",\n" +
    "        \"copy_to\": \"all\"\n" +
    "      },\n" +
    "      \"starName\":{\n" +
    "        \"type\": \"keyword\"\n" +
    "      },\n" +
    "      \"business\":{\n" +
    "        \"type\": \"keyword\"\n" +
    "      },\n" +
    "      \"location\":{\n" +
    "        \"type\": \"geo_point\"\n" +
    "      },\n" +
    "      \"pic\":{\n" +
    "        \"type\": \"keyword\",\n" +
    "        \"index\": false\n" +
    "      },\n" +
    "      \"all\":{\n" +
    "        \"type\": \"text\",\n" +
    "        \"analyzer\": \"ik_max_word\"\n" +
    "      }\n" +
    "    }\n" +
    "  }\n" +
    "}";
}

文档的操作

java 复制代码
@SpringBootTest
public class HotelDocumentTests {
  // 核心对象
  private RestHighLevelClient client;

  // 需要从数据库中查数据存入es,装配业务
  @Autowired(required = false)
  private IHotelService service;

  @BeforeEach
  void setUp(){
    this.client = new RestHighLevelClient(RestClient.builder(
      HttpHost.create("http://localhost:9200")
    ));
  }

  @AfterEach
  void tearDown() throws  Exception{
    this.client.close();
  }

  // 从数据库新增一条数据到es
  @Test
  void addDocument() throws Exception{
    // 从数据库查询一条数据
    Hotel hotel = service.getById(395434);
    System.out.println(hotel);
    // 转换为文档类型
    HotelDoc hotelDoc = new HotelDoc(hotel);
    // 将文档类型转为JSON格式
    String json = JSON.toJSONString(hotelDoc);
    // 准备request请求对象
    IndexRequest request = new IndexRequest("hotels").id(hotelDoc.getId().toString());
    // 准备JSON文档
    request.source(json, XContentType.JSON);
    // 发送请求
    client.index(request, RequestOptions.DEFAULT);
  }

  // 从es中删除一条数据
  @Test
  void deleteDocument() throws Exception{
    // 准备删除请求Request
    DeleteRequest request = new DeleteRequest("hotels", "395434");
    // 发送请求
    client.delete(request,RequestOptions.DEFAULT);
  }

  // 修改es中的数据
  @Test
  void updateDocument() throws  Exception{
    // 准备修改请求UpdateRequest
    UpdateRequest request = new UpdateRequest("hotels", "395434");
    // 准备请求参数(要修改的数据内容)
    request.doc(
      "name","W酒店",
      "city","西安",
      "price","2000",
      "starName","五星级"
    );
    // 发送请求
    client.update(request, RequestOptions.DEFAULT);
  }

  // 从es中查询一条数据
  @Test
  void getDocumentById() throws  Exception{
    // 准备查询请求GetRequest
    GetRequest getRequest = new GetRequest("hotels", "395434");
    // 发送请求,得到响应
    GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
    // 解析响应结果
    String json = response.getSourceAsString();
    HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);
    System.out.println(hotelDoc);
  }

  // 批量新增数据到es
  @Test
  void addAllDocument() throws  Exception{
    // 数据库全查
    List<Hotel> hotels = service.list();
    // 准备请求
    BulkRequest bulkRequest = new BulkRequest();
    // 准备参数
    for(Hotel hotel : hotels){
      // 类型转化
      HotelDoc hotelDoc = new HotelDoc(hotel);
      // 请求添加数据
      bulkRequest.add(new IndexRequest("hotels").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));
    }
    // 发送请求
    client.bulk(bulkRequest,RequestOptions.DEFAULT);
  }

  // 解析对象方法
  public void show(SearchResponse response){
    // 解析响应
    SearchHits searchHits = response.getHits();
    long total = searchHits.getTotalHits().value;
    System.out.println("总计查询数据:"+total+"条");
    SearchHit[] hits = searchHits.getHits();
    for(SearchHit hit :hits){
      /// 获取文档source
      String json = hit.getSourceAsString();
      // 反序列化
      HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
      System.out.println("hotelDoc="+hotelDoc);
    }
  }
  /*---------- 全查 ------------*/
  // 全查
  @Test
  void findAllDocument() throws IOException{
    // 准备request
    SearchRequest request = new SearchRequest("hotels");

    // 2.准备DSL,QueryBuilders构造查询条件
    request.source().query(QueryBuilders.matchAllQuery());

    // 3.发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  /*-------------- 全文检索 ---------------*/
  // 查询all字段内容中含有如家的
  @Test
  void testMacth() throws IOException{
    // 准备请求
    SearchRequest request = new SearchRequest("hotels");
    // 准备DSL
    request.source().
      query(QueryBuilders.matchQuery("all","如家"));

    // 发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  // 查询字段name、city中有上海的
  @Test
  void testMultiMatchQuery()throws IOException {
    // 准备请求
    SearchRequest request = new SearchRequest("hotels");
    // 准备DSL
    request.source()
      .query(QueryBuilders.multiMatchQuery("上海","name","city"));
    // 发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  /*------------ 精确查询 ------------------*/

  // term:根据词条精准查询(字段等值查询)
  @Test
  void testTerm() throws  IOException{
    // 准备请求
    SearchRequest request = new SearchRequest("hotels");
    // 准备DSL
    request.source()
      .query(QueryBuilders.termQuery("brand","希尔顿"));

    // 发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  // range范围查询
  @Test
  void  testRange() throws IOException {
    // 准备请求
    SearchRequest request = new SearchRequest("hotels");
    // 准备DSL
    request.source()
      .query(QueryBuilders.rangeQuery("price").gte(200).lte(300));
    // 发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  // ids查询
  @Test
  void testIds() throws IOException  {
    // 准备请求
    SearchRequest request = new SearchRequest("hotels");
    // 准备DSL
    request.source()
      .query(QueryBuilders.idsQuery().addIds("395434","3532"));
    // 发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  /*------------- 复合查询 --------------------*/
  // bool复合查询
  @Test
  void testBool() throws IOException{
    // 准备请求
    SearchRequest request = new SearchRequest("hotels");
    // 准备条件
    /*-- 方式1  ----*/
    //        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    //        boolQueryBuilder.must(QueryBuilders.termQuery("city","北京"));
    //        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(500));
    //        // 准备DSL
    //        request.source().query(boolQueryBuilder);

    /*---- 方式2 ----*/
    request.source()
      .query(QueryBuilders.boolQuery()
             .must(QueryBuilders.termQuery("city","北京"))
             .filter(QueryBuilders.rangeQuery("price").lte(500)));
    // 发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  // 自定义分页方式
  @Test
  void testPageAndSort() throws IOException{
    int page = 1;   //页码
    int size = 5;   //步长
    String searchName="希尔顿"; // 查询条件
    // 准备请求
    SearchRequest request = new SearchRequest("hotels");
    if (searchName == null){
      request.source().query(QueryBuilders.matchAllQuery());
    }else {
      request.source().query(QueryBuilders.matchQuery("brand",searchName));
    }
    // 自定义分页
    request.source().from((page-1)*size).size(size);
    // 自定义排序
    request.source().sort("price", SortOrder.DESC);
    // 发送请求
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // 解析结果
    show(response);
  }
}

小结:

文档的查询操作实现步骤大致都相同:

  1. 准备请求
  2. 准备DSL
  3. 发送请求
相关推荐
2402_857589366 分钟前
SpringBoot框架:作业管理技术新解
java·spring boot·后端
杨荧26 分钟前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
zmd-zk1 小时前
kafka+zookeeper的搭建
大数据·分布式·zookeeper·中间件·kafka
计算机-秋大田3 小时前
基于Spring Boot的船舶监造系统的设计与实现,LW+源码+讲解
java·论文阅读·spring boot·后端·vue
代码之光_19804 小时前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
戴眼镜的猴5 小时前
Spring Boot的过滤器与拦截器的区别
spring boot
尘浮生5 小时前
Java项目实战II基于Spring Boot的光影视频平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
尚学教辅学习资料6 小时前
基于SpringBoot的医药管理系统+LW示例参考
java·spring boot·后端·java毕业设计·医药管理