SpringBoot–middleware technology-3: Integrate mongodb, integrate ElasticSearch, attached case with code (simple and easy to understand)

SpringBoot integrates mongodb

Implementation steps:

  1. pom file import coordinates

    <!--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 configuration file configures mongodb:

    spring:
      data:
        mongodb:
          uri: mongodb://localhost/spring
    
  3. Just create a pojo

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public class Book {<!-- -->
        private int id;
        private String name;
        private String type;
        private String description;
    }
    
  4. test:

    @SpringBootTest
    class SpringbootMongodb01ApplicationTests {<!-- -->
    
      @Autowired(required = false)
      private MongoTemplate mongoTemplate;
    
      @Test
      void contextLoads() {<!-- -->
        Book book = new Book();
        book.setId(4);
        book.setName("Zhang San");
        book.setType("Awesome");
        book.setDescription("Really awesome");
        mongoTemplate.save(book);
      }
    
      @Test
      void find(){<!-- -->
        List<Book> all = mongoTemplate.findAll(Book.class);
        System.out.println(all);
      }
    }
    

    Assemble the MongoTemplate template class and call the method

Summary of integrating MongoDB:

  1. Guide coordinates
  2. Write configuration file
  3. Core class MongoTemplate call

SpringBoot integrates ElasticSearch

Prerequisite preparation: database + ES

Database table creation statement:

DROP TABLE IF EXISTS `tb_hotel`;
CREATE TABLE `tb_hotel` (
  `id` bigint(20) NOT NULL COMMENT 'hotel id',
  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Hotel name',
  `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Hotel address',
  `price` int(10) NOT NULL COMMENT 'hotel price',
  `score` int(2) NOT NULL COMMENT 'Hotel rating',
  `brand` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Hotel brand',
  `city` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'City',
  `star_name` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Hotel star rating, 1 to 5 stars, 1 to 5 diamonds',
  `business` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Business District',
  `latitude` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'latitude',
  `longitude` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT 'Longitude',
  `pic` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'Hotel Picture',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;

Implementation steps:

  1. pom file to coordinates

    <properties>
      <!--Lock jdk version-->
      <java.version>1.8</java.version>
      <!--Lock es version-->
      <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 configuration file

    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. Create entity class:

    Entity class corresponding to database table

    @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;//Longitude
      private String latitude;//Latitude
      private String pic;
    }
    

    Entity class corresponding to ES

    @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;
    // The construction method is used for type conversion to replace the longitude and latitude in the database with coordinate location, so HotelDoc is slightly different.
      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 layer:

    @Mapper
    public interface HotelMapper extends BaseMapper<Hotel> {<!-- -->
    }
    
  5. service layer:

    interface:

    public interface IHotelService extends IService<Hotel> {<!-- -->
    }
    

    Implementation class:

    @Service
    public class HotelServiceImp extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {<!-- -->
    }
    
  6. The demonstration is carried out in juint, demonstrating the operation of the index library and documents

Operation of index library

  • Determine whether the index library exists (actually a query)
  • Create index library
  • Delete index library
@SpringBootTest
class SpringbootEs01ApplicationTests {<!-- -->
// Manipulate the core object of es
  private RestHighLevelClient client;
// The unit test is executed before, telling the port number of the core object es. Fixed syntax
  @BeforeEach
  void setUp(){<!-- -->
    this.client = new RestHighLevelClient(RestClient.builder(
      HttpHost.create("http://localhost:9200")
    ));
  }
// Executed after unit tests
  @AfterEach
  void tearDown() throws Exception{<!-- -->
    this.client.close();
  }

  // Determine whether the index library exists
  @Test
  void testExistsHotelIndex() throws Exception {<!-- -->
    GetIndexRequest request = new GetIndexRequest("hotels");
    boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    System.err.println(exists? "The index library already exists":"The index library does not exist");
  }

  //Create index library
  @Test
  void createHotelIndex() throws Exception{<!-- -->
    //Create Request object
    CreateIndexRequest request = new CreateIndexRequest("hotels");
    // Prepare request parameters: DSL statement
    request.source(HotelConstants.MAPPING_TEMPLATE, XContentType.JSON);
    // send request
    client.indices().create(request,RequestOptions.DEFAULT);
  }

  // Delete index library
  @Test
  void delteHotelIndex() throws Exception{<!-- -->
    //Create Request object
    DeleteIndexRequest request = new DeleteIndexRequest("hotels");
    // send request
    client.indices().delete(request,RequestOptions.DEFAULT);
  }
}

When creating an index library, mapping is required. The mapping is often a complex and long JSON, so write a separate class. The mapping for creating the index library above is as follows

You can write it in postman and paste it here

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

Document operations

@SpringBootTest
public class HotelDocumentTests {<!-- -->
  // core object
  private RestHighLevelClient client;

  // Need to check data from the database and store it in es, assembly business
  @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();
  }

  //Add a piece of data from the database to es
  @Test
  void addDocument() throws Exception{<!-- -->
    // Query a piece of data from the database
    Hotel hotel = service.getById(395434);
    System.out.println(hotel);
    // Convert to document type
    HotelDoc hotelDoc = new HotelDoc(hotel);
    //Convert document type to JSON format
    String json = JSON.toJSONString(hotelDoc);
    // Prepare request request object
    IndexRequest request = new IndexRequest("hotels").id(hotelDoc.getId().toString());
    // Prepare JSON document
    request.source(json, XContentType.JSON);
    // send request
    client.index(request, RequestOptions.DEFAULT);
  }

  //Delete a piece of data from es
  @Test
  void deleteDocument() throws Exception{<!-- -->
    // Prepare to delete request Request
    DeleteRequest request = new DeleteRequest("hotels", "395434");
    // send request
    client.delete(request,RequestOptions.DEFAULT);
  }

  //Modify the data in es
  @Test
  void updateDocument() throws Exception{<!-- -->
    // Prepare to modify the request UpdateRequest
    UpdateRequest request = new UpdateRequest("hotels", "395434");
    // Prepare request parameters (data content to be modified)
    request.doc(
      "name","W Hotel",
      "city","Xi'an",
      "price","2000",
      "starName","five-star"
    );
    // send request
    client.update(request, RequestOptions.DEFAULT);
  }

  // Query a piece of data from es
  @Test
  void getDocumentById() throws Exception{<!-- -->
    // Prepare query request GetRequest
    GetRequest getRequest = new GetRequest("hotels", "395434");
    //Send request and get response
    GetResponse response = client.get(getRequest, RequestOptions.DEFAULT);
    // Parse the response result
    String json = response.getSourceAsString();
    HotelDoc hotelDoc = JSON.parseObject(json,HotelDoc.class);
    System.out.println(hotelDoc);
  }

  // Add data to es in batches
  @Test
  void addAllDocument() throws Exception{<!-- -->
    // Full database search
    List<Hotel> hotels = service.list();
    // Prepare request
    BulkRequest bulkRequest = new BulkRequest();
    // Prepare parameters
    for(Hotel hotel : hotels){<!-- -->
      // type conversion
      HotelDoc hotelDoc = new HotelDoc(hotel);
      //Request to add data
      bulkRequest.add(new IndexRequest("hotels").id(hotelDoc.getId().toString()).source(JSON.toJSONString(hotelDoc),XContentType.JSON));
    }
    // send request
    client.bulk(bulkRequest,RequestOptions.DEFAULT);
  }

  // Parse object method
  public void show(SearchResponse response){<!-- -->
    // Parse the response
    SearchHits searchHits = response.getHits();
    long total = searchHits.getTotalHits().value;
    System.out.println("Total query data:" + total + "bar");
    SearchHit[] hits = searchHits.getHits();
    for(SearchHit hit :hits){<!-- -->
      /// Get document source
      String json = hit.getSourceAsString();
      //Deserialize
      HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
      System.out.println("hotelDoc=" + hotelDoc);
    }
  }
  /*---------- Full search ------------*/
  // Check all
  @Test
  void findAllDocument() throws IOException{<!-- -->
    // Prepare request
    SearchRequest request = new SearchRequest("hotels");

    // 2. Prepare DSL, QueryBuilders construct query conditions
    request.source().query(QueryBuilders.matchAllQuery());

    // 3.Send request
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  /*-------------- Full Text Search ---------------*/
  // Query if the all field content contains Home Inns
  @Test
  void testMacth() throws IOException{<!-- -->
    // Prepare request
    SearchRequest request = new SearchRequest("hotels");
    // Prepare DSL
    request.source().
      query(QueryBuilders.matchQuery("all","Home Inn"));

    // send request
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  // Query fields name and city include Shanghai
  @Test
  void testMultiMatchQuery()throws IOException {<!-- -->
    // Prepare request
    SearchRequest request = new SearchRequest("hotels");
    // Prepare DSL
    request.source()
      .query(QueryBuilders.multiMatchQuery("Shanghai","name","city"));
    // send request
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  /*--------------------- Precise query ------------------*/

  // term: precise query based on term (field equivalent query)
  @Test
  void testTerm() throws IOException{<!-- -->
    // Prepare request
    SearchRequest request = new SearchRequest("hotels");
    // Prepare DSL
    request.source()
      .query(QueryBuilders.termQuery("brand","Hilton"));

    // send request
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  //range range query
  @Test
  void testRange() throws IOException {<!-- -->
    // Prepare request
    SearchRequest request = new SearchRequest("hotels");
    // Prepare DSL
    request.source()
      .query(QueryBuilders.rangeQuery("price").gte(200).lte(300));
    // send request
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  // ids query
  @Test
  void testIds() throws IOException {<!-- -->
    // Prepare request
    SearchRequest request = new SearchRequest("hotels");
    // Prepare DSL
    request.source()
      .query(QueryBuilders.idsQuery().addIds("395434","3532"));
    // send request
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  /*------------- Compound query --------------------*/
  // bool compound query
  @Test
  void testBool() throws IOException{<!-- -->
    // Prepare request
    SearchRequest request = new SearchRequest("hotels");
    //Preparation conditions
    /*-- Mode 1 ----*/
    // BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    // boolQueryBuilder.must(QueryBuilders.termQuery("city","Beijing"));
    // boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").lte(500));
    // // Prepare DSL
    // request.source().query(boolQueryBuilder);

    /*----Method 2 ----*/
    request.source()
      .query(QueryBuilders.boolQuery()
             .must(QueryBuilders.termQuery("city","Beijing"))
             .filter(QueryBuilders.rangeQuery("price").lte(500)));
    // send request
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    show(response);
  }

  // Custom paging method
  @Test
  void testPageAndSort() throws IOException{<!-- -->
    int page = 1; //Page number
    int size = 5; //step size
    String searchName="Hilton"; // Query conditions
    // Prepare request
    SearchRequest request = new SearchRequest("hotels");
    if (searchName == null){<!-- -->
      request.source().query(QueryBuilders.matchAllQuery());
    }else {<!-- -->
      request.source().query(QueryBuilders.matchQuery("brand",searchName));
    }
    // Custom paging
    request.source().from((page-1)*size).size(size);
    //Custom sorting
    request.source().sort("price", SortOrder.DESC);
    // send request
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    // parse results
    show(response);
  }
}

summary:

The steps to implement document query operations are roughly the same:

  1. Prepare request
  2. Prepare for DSL
  3. send request