网上一堆复杂的操作,其实spring-data-elsaticsearch可以很简便的写,它遵循springdata的写法。

elasticsearch选用的是7.16版本,兼容7.x版本,主要使用的是spring-data-elasticsearch 因为感觉这个很好用 其他的工具也可以,主要是顺心顺手( •̀ ω •́ )

添加pom.xml依赖

    <properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.17.6</elasticsearch.version>
    </properties>
    <dependencies>
<!--elasticsearch data-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!--我study主要写在测试类里面 所以导入测试类依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>2.7.5</version>
    <scope>test</scope>
</dependency>
<!-- 单元测试依赖 -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
</dependencies>

编写yml文件

server:
  port: 8080
spring:
  elasticsearch:
    uris: localhost:9200

编写实体类

package com.example.elasticsearchstudy.domain;

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.stereotype.Component;

import java.io.Serializable;


/**
 * @author liwenzhu
 */
@Component
@Data
@Document(indexName = "hotel")
public class Hotel implements Serializable {

    /** 酒店id*/
    @Id
    private String id;

    /** 酒店名称*/
    @Field(type = FieldType.Keyword)
    private String name;

    /** 酒店地址 */
    @Field(type = FieldType.Keyword)
    private String address;

    /** 酒店价格 */
    @Field(type = FieldType.Double)
    private Integer price;

    /** 酒店评分 */
    @Field(type = FieldType.Double)
    private Double score;

    /** 酒店品牌 */
    @Field(type = FieldType.Keyword)
    private String brand;

    /** 所在城市 */
    @Field(type = FieldType.Keyword)
    private String city;

    /** 酒店星级 酒店星级,1星到5星,1钻到5钻 */
    @Field(type = FieldType.Keyword)
    private String starName;

    /** 商圈 */
    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String business;

    /** 纬度 */
    @Field(type = FieldType.Keyword)
    private String latitude;

    /** 经度 */
    @Field(type = FieldType.Keyword)
    private String longitude;

    /** 酒店图片 */
    @Field(type = FieldType.Keyword)
    private String pic;
}

新建一个repository/HotelRepository

package com.example.elasticsearchstudy.repository;

import com.example.elasticsearchstudy.domain.Hotel;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Service;

/**
 * @author liwenzhu
 */
@Service
public interface HotelRepository extends ElasticsearchRepository<Hotel,String> {
}

编写测试类

package com.example.elasticsearchstudy;

import com.example.elasticsearchstudy.domain.Hotel;
import com.example.elasticsearchstudy.repository.HotelRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

@RunWith(SpringRunner.class)
@SpringBootTest
public class LiwenzhuTest {
    @Resource
    private HotelRepository repository;

    @Test
    public void testCreateDoc() {
        Hotel hotel = new Hotel();
        hotel.setName("京西大酒店");
        hotel.setAddress("xxx路");
        hotel.setPrice(2000);
        hotel.setScore(4.0);
        hotel.setBrand("李文铸牌");
        hotel.setCity("福州");
        hotel.setStarName("四星");
        hotel.setBusiness("福州儿童公园路");
        hotel.setLatitude("30.251433");
        hotel.setLongitude("120.47522");
        hotel.setPic("https://m.tuniucdn.com/filebroker/cdn/res/07/36/073662e1718fccefb7130a9da44ddf5c_w200_h200_c1_t0.jpg");
        repository.save(hotel);
    }
}

因为是spring-data-elasticsearch 所以crud是遵循spring-data的风格的
增加和修改都是save方法
删除就是delete方法,不过他删除都是根据id删的,所以要么deleteById,要么就是delete实体类的id有值
查询遵循spring-data风格
比如你的方法名叫做:findByTitle,那么它就知道你是根据title查询,然后自动帮你完成,无需写实现类。

在这里插入图片描述

高亮显示

在repository方法上使用@Highlight注解即可
然后在SearchHit就可以看到获取的高亮信息了,比原生的方法好用很多。

@Highlight(fields = {
        @HighlightField(name = "city"),
        @HighlightField(name = "name")
})
List<SearchHit<Hotel>> findByCityAndName(String city,String name);

模糊查询

遵循JPA的查询规范即可 findByxxxContains 相当于 % xxx %,而findByxxxLike 相当于 xxx %,所以模糊匹配根据需求来。

List<Hotel> findByNameContains(String name);

分页

分页的写法也非常简单,参数多加一个Pageable就可以了
同样是在repository层

List<Hotel> findByNameContains(String name,Pageable pageable);

调用层

//这个地方正常page和size是参数传进来的,但是因为是Test类,不允许这样的操作,所以在这里备注一下。

@Test
public void likeQuery() {
    //分页参数
    int page = 1;
    int size = 10;
    List<Hotel> nameList = hotelRepository.findByNameContains("北京",PageRequest.of(page - 1, size));
    System.out.println(nameList);
}

全文检索

实体类加上对应的字段 这个额外字段必须和索引库的一致

/** * 由其他属性copy而来,主要用于搜索功能,不需要储存数据 */
 @JsonIgnore @Field(type = FieldType.Text, analyzer = "ik_max_word", ignoreFields = "descriptiveContent", excludeFromSource = true)
 private String descriptiveContent;

repository层

/**
 * 全文检索
 * @param descriptiveContent 检索的字段
 * @return
 */
List<Hotel> findByAll(String descriptiveContent);

排序

/**
 * 排序
 * @param descriptiveContent 检索的字段
 * @return
 */
List<Hotel> findByAllOrderByPriceDesc(String descriptiveContent);

gitee: https://gitee.com/soulsinger/elasticsearch-study.git

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐