SpringBoot 2.X 整合 Elasticsearch

SpringBoot 整合 Elasticsearch

官方文档介绍

https://spring.io/projects/spring-data-elasticsearch
image.png

ElasticSearch安装版本,项目集成版本对应关系图


image.png

Spring Data Elasticsearch

Spring Data Elasticsearch是Spring提供的一种以Spring Data风格来操作数据存储的方式,它可以避免编写大量的样板代码。

常用注解

@Document 标示映射到Elasticsearch文档上的领域对象

@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
public @interface Document {

    /**
     * 索引库名次,mysql中数据库的概念
     * Name of the Elasticsearch index.
     * 
    *
  • Lowercase only
  • *
  • , |, ` ` (space character), ,, #/li> *
  • Cannot start with -, _, +
  • *
  • Cannot be . or ..
  • *
  • Cannot be longer than 255 bytes (note it is bytes, so multi-byte characters will count towards the 255 limit * faster)
  • *
*/ String indexName(); /** * Use server-side settings when creating the index. */ boolean useServerConfiguration() default false; /** *默认分片数 * Number of shards for the index {@link #indexName()}. Used for index creation.
* With version 4.0, the default value is changed from 5 to 1 to reflect the change in the default settings of * Elasticsearch which changed to 1 as well in Elasticsearch 7.0. */ short shards() default 1; /** * 默认副本数量 * Number of replicas for the index {@link #indexName()}. Used for index creation. */ short replicas() default 1; /** * Refresh interval for the index {@link #indexName()}. Used for index creation. */ String refreshInterval() default "1s"; /** * Index storage type for the index {@link #indexName()}. Used for index creation. */ String indexStoreType() default "fs"; /** * Configuration whether to create an index on repository bootstrapping. */ boolean createIndex() default true; /** * Configuration of version management. */ VersionType versionType() default VersionType.EXTERNAL; }

@Id 表示是文档的id,文档可以认为是mysql中表行的概念

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
public @interface Id {
}

@Field

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
@Inherited
public @interface Field {
    //文档中字段的类型
    FieldType type() default FieldType.Auto;
    //是否建立倒排索引
    boolean index() default true;

    DateFormat format() default DateFormat.none;

    String pattern() default "";
    //是否进行存储
    boolean store() default false;

    boolean fielddata() default false;

    String searchAnalyzer() default "";
    //分词器名次
    String analyzer() default "";

    String normalizer() default "";

    String[] ignoreFields() default {};

    boolean includeInParent() default false;

    String[] copyTo() default {};
}
为文档自动指定元数据类型
public enum FieldType {
    Text,//会进行分词并建了索引的字符类型
    Integer,
    Long,
    Date,
    Float,
    Double,
    Boolean,
    Object,
    Auto,//自动判断字段类型
    Nested,//嵌套对象类型
    Ip,
    Attachment,
    Keyword;//不会进行分词建立索引的类型

    private FieldType() {
    }
}



在SpringBoot data Elasticsearch 操作方式有2种:一种是继承ElasticsearchRepository接口,另一种是ElasticsearchTemplate.

第一种方式:继承ElasticsearchRepository接口
image.png

image.png

先创建实体类

/**
 * 搜索商品的信息
 */
@Data
@EqualsAndHashCode(callSuper = false)
//indexName 索引库名次,mysql中数据库的概念
//type 类型
//shards 默认分片数
//replicas 默认副本数量
@Document(indexName = "pms",type = "product",shards = 1,replicas = 0)
public class EsProduct implements Serializable {
    private static final long serialVersionUID = -1L;

    @Id
    private Long id;
    @Field(type = FieldType.Keyword)
    private String productSn;
    private Long brandId;
    @Field(type = FieldType.Keyword)
    private String brandName;
    @Field(type = FieldType.Keyword)
    private String productCategoryName;
    private String pic;
    @Field(analyzer = "ik_max_word",type = FieldType.Text)
    private String name;
    @Field(analyzer = "ik_max_word",type = FieldType.Text)
    private String subTitle;
    @Field(analyzer = "ik_max_word",type = FieldType.Text)
    private String keywords;
    private BigDecimal price;
    private Integer sort;
    @Field(type =FieldType.Nested)
    private List attrValueList;
...get set 方法

继承ElasticsearchRepository接口

/**
 * 搜索商品ES操作类
 *
 * 在接口中直接指定 **查询方法名** 称便可查询,无需进行实现,
 * 如商品表中有商品名称、标题和关键字,
 * 直接定义以下查询,就可以对这三个字段进行全文搜索。
 */
public interface EsProductRepository extends ElasticsearchRepository {

    /**
     * 搜索查询
     * @param name  商品名称
     * @param subTitle  商品标题
     * @param keywords  商品关键字
     * @param page  分页信息
     * @return
     * 必须按提示命名
     */
    Page findByNameOrSubTitleOrKeywords(String name, String subTitle, String keywords, Pageable page);
    /**
     * "match_all": {}
     * @param name
     * @param pageable
     * @return
     */
//    @Query("{"bool" : {"must" : {"field" : {"name" : "?0"}}}}")
    Page findByName(String name,Pageable pageable);

}

EsProductService 实现类

/**
 * EsProductService 实现类
 */
@Service
public class EsProductServiceImpl implements EsProductService {
    private static final Logger logger = LoggerFactory.getLogger(EsProductServiceImpl.class);

    @Autowired
    private EsProductDao productDao;

    @Autowired
    private EsProductRepository productRepository;

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Override
    public int importAll() {
        //数据库查询所有商品信息
        List esProductList = productDao.getAllEsProductList(null);
        logger.info("查询所有商品:{}",esProductList.toString());
        //把所有的商品信息放入es中
        Iterable esProductIterable = productRepository.saveAll(esProductList);
        Iterator iterator = esProductIterable.iterator();
        int result =0;
        while (iterator.hasNext()) {
            result++;
            iterator.next();
        }
        //放入了多少条
        return result;
    }

    @Override
    public void delete(Long id) {
        productRepository.deleteById(id);
    }

    @Override
    public EsProduct create(Long id) {
        EsProduct result = null;
        List esProductList = productDao.getAllEsProductList(id);
        //从数据库中查询商品,把商品放入es中
        if (esProductList.size() > 0){
            EsProduct esProduct = esProductList.get(0);
            result = productRepository.save(esProduct);
        }
        return result;
    }

    @Override
    public void delete(List ids) {
        //org.springframework.util.CollectionUtils;
        if ( !CollectionUtils.isEmpty(ids) ){
            List esProductList = new ArrayList<>();
            for (Long id:ids){
                EsProduct esProduct = new EsProduct();
                esProduct.setId(id);
                esProductList.add(esProduct);
            }
            productRepository.deleteAll(esProductList);
        }
    }

    @Override
    public Page search(String keyword, Integer pageNum, Integer pageSize) {
        // 分页
        Pageable pageable = PageRequest.of(pageNum,pageSize);
        //
//        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
//                .must(QueryBuilders.matchQuery("name",keyword))
//                .must(QueryBuilders.matchQuery("subTitle",keyword))
//                .must(QueryBuilders.matchQuery("keywords",keyword));

        QueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("name",keyword))
                .must(QueryBuilders.matchQuery("subTitle",keyword))
                .must(QueryBuilders.matchQuery("keywords",keyword));

//        return productRepository.search(queryBuilder,pageable);
        return productRepository.findByNameOrSubTitleOrKeywords(keyword,keyword,keyword,pageable);
    }

    @Override
    public List searchAll() {
        Iterable iterable = productRepository.findAll();
        Iterator iterator = iterable.iterator();
        List list = new ArrayList<>();
        while (iterator.hasNext()){
            list.add(iterator.next());
        }
        return list;
    }

    @Override
    public Page searchByName(String keyword, Integer pageNum, Integer pageSize) {
        // 分页
        Pageable pageable = PageRequest.of(pageNum,pageSize);

        return productRepository.findByName(keyword,pageable);
    }

}


第二种方式:ElasticsearchTemplate

org.springframework.data.elasticsearch.core.ElasticsearchTemplate

image.png

创建数据

org.springframework.data.elasticsearch.core.query.IndexQuery;
//创建单条数据
public String index(IndexQuery query) {}
//创建单条数据
public  boolean createIndex(Class clazz) {}
//批量创建数据
public void bulkIndex(List queries) {}
    public void addAll( EsProduct esProduct ){
        IndexQuery indexQuery = new IndexQueryBuilder()
                .withId(esProduct.getProductSn())
                .withObject(esProduct)
                .build();
        //创建单条数据
        elasticsearchTemplate.index(indexQuery);
        elasticsearchTemplate.createIndex(EsProduct.class);
        //批量创建数据
        List indexQueryList = new ArrayList<>();
        indexQueryList.add(new IndexQueryBuilder().withId("")
                .withIndexName("索引名称").withObject(esProduct).build());
        indexQueryList.add(new IndexQueryBuilder().withId("")
                .withIndexName("索引名称").withObject(esProduct).build());
        elasticsearchTemplate.bulkIndex(indexQueryList);
    }

删除数据

//根据类对象删除
public  boolean deleteIndex(Class clazz) {}
// 根据索引名删除
public boolean deleteIndex(String indexName) {}
//
//org.springframework.data.elasticsearch.core.query.DeleteQuery
//org.elasticsearch.index.query.QueryBuilder
public  void delete(DeleteQuery deleteQuery, Class clazz) {}

更新数据

//单个更新
//org.springframework.data.elasticsearch.core.query.UpdateQuery;
//org.elasticsearch.action.update.UpdateRequest;
//org.springframework.data.elasticsearch.core.query.UpdateQueryBuilder
public UpdateResponse update(UpdateQuery query) {}
// 批量更新
public void bulkUpdate(List queries) {}

查询

//
//org.springframework.data.elasticsearch.core.query.SearchQuery;
//org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
//org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
public  List queryForIds(SearchQuery query) {}
//
public  List queryForList(StringQuery query, Class clazz){}
//
public  T queryForObject(StringQuery query, Class clazz) {}
//
public  AggregatedPage queryForPage(SearchQuery query, Class clazz) {}
//
//org.springframework.data.elasticsearch.core.query.CriteriaQuery ;
//org.springframework.data.elasticsearch.core.query.Criteria;
public  List queryForList(CriteriaQuery query, Class clazz) {}

示例

        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.queryStringQuery("小米"))
                .withPageable(new PageRequest(0, 20))
                .build();
        List list = elasticsearchTemplate.queryForList(searchQuery, EsProduct.class);

//排序
        Pageable pageable= new PageRequest(0, 20,new Sort(Sort.Direction.DESC, "name"));
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.queryStringQuery("华为"))
                .withPageable(pageable)
                .build();
        Page list = elasticsearchTemplate.queryForPage(searchQuery, EsProduct.class);

//模糊查找
        Pageable pageable = new PageRequest(0, 10);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.matchQuery("name", "苹果"))
                .withPageable(pageable)
                .build();
        List list = elasticsearchTemplate.queryForList(searchQuery, EsProduct.class);
//Term全等查询
        Pageable pageable = new PageRequest(0, 10);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(QueryBuilders.termQuery("name", "华为"))
                .withPageable(pageable)
                .build();
        List list = elasticsearchTemplate.queryForList(searchQuery, EsProduct.class);

//组合查询
        QueryBuilder filterQuery = QueryBuilders
                .boolQuery()
                .filter(QueryBuilders.termQuery("name", "小米"))
                .filter(QueryBuilders.termQuery("author", "雷军"));
        SearchQuery searchQuerys = new NativeSearchQueryBuilder().withQuery(filterQuery).build();
        List lists = elasticsearchTemplate.queryForList( searchQuerys, EsProduct.class);

你可能感兴趣的:(SpringBoot 2.X 整合 Elasticsearch)