Elasticsearch的JavaAPI的基本使用

环境:CentOS7、Elasticsearch6.4.0
*** 本次测试使用ES与SpringData集成 ***


一、创建maven项目,向pom文件中导入配置

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-elasticsearch</artifactId>
            <version>3.1.3.RELEASE</version>
        </dependency>
       
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.3.RELEASE</version>
        </dependency>
       
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>

二、实体类配置

@Data
@AllArgsConstructor
@NoArgsConstructor 
//以上为lombok动态实现完全封装的注解
import org.springframework.data.elasticsearch.annotations.Document;
//Document注解,用来标识实体类对应的索引名(indexName ),类型(type),分区等
@Document(indexName = "tp",type = "poetry")
public class Poetry {
    @Id
    //标识主键
    private String id;
    //为文本类型字段指定(插入,查询)分词器,指定字段类型
    @Field(analyzer = "ik_max_word",searchAnalyzer = "ik_max_word",type = FieldType.Text)
    private String name;
    
	@Field(type = FieldType.Integer)
	private Integer age;
	
	@Field(type = FieldType.Double)
	private double salary;
    
    @DateTimeFormat(style = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd")
    @Field(type = FieldType.Date)
    //指定日期类型格式
    private Date birthday;
}

实体类如上配置,可直接使用JavaAPI进行插入,无需手动创建索引,类型的字段属性同注解配置


三、使用ES的JavaAPI

1. 基础的repository接口:提供基本的增删改查和根据方法名的查询(ES提供实现)


import com.baizhi.entity.User;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
/**
* 基础操作的es repository接口(定义的有通用的增删改查方法)
* ElasticsearchRepository<实体,主键类型>
* 这里只要继承ElasticsearchRepository接口就可以使用es为我们提供的方法
* 一些其他的方法可以通过给抽象方法以指定格式起名来让es默认实现
* 本类中提供了一些简单的命名
* 注:聚合查询不能使用这种方式
* @author liudy
*/
public interface UserRepository extends ElasticsearchRepository<User,String> {
	/**
	 * 根据年龄区间查询数据 并根据年龄降序排列
	 */
	 public List<User> findByAgeBetweenOrderByAgeDesc(int start,int end);
	 /**
	 * 查询真实姓名已“王”开头的数据
	 */
	 public List<User> findByRealnameStartingWith(String startStr);
	 /**
	 * 通过Query注解自定义查询表达式
	 */
	 @Query("{\"bool\" : {\"must\" : {\"fuzzy\" : {\"name\" : \"?0\"}}}}")
	 public List<User> findByNameLike(String name);
}

启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;

@SpringBootApplication
//配置es接口所在的包
@EnableElasticsearchRepositories("com.dao")
public class TpApplication {

    public static void main(String[] args) {
        SpringApplication.run(TpApplication.class, args);
    }

}

测试

import com.baizhi.entity.User;
import com.baizhi.es.dao.UserRepository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Date;
import java.util.List;
import java.util.Optional;
/**
* @author gaozhy
* @date 2018/12/29.9:30
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext-es.xml")
public class UserRepositoryTest {
@Autowired
  private UserRepository userRepository;
  /**
  * 查所有
  */
  @Test
  public void testQueryAll(){
    Iterable<User> users = userRepository.findAll();
    for (User user : users) {
      System.out.println(user);
   }
 }
  /**
  * 查询所有 并根据年龄倒序排列
  */
  @Test
  public void testQueryBySort(){
    Iterable<User> users = userRepository.findAll(Sort.by(Sort.Direction.DESC, "age"));
    for (User user : users) {
      System.out.println(user);
   }
 }
  /**
  * 根据id查询
  */
  @Test
  public void testQueryById(){
    Optional<User> user = userRepository.findById("1");
    System.out.println(user.get());
 }
  /**
  * 新增或者修改数据
  */
  @Test
  public void testAdd(){
    User user = userRepository.save(new User("6", "wb", "王八", 26, 10000D, new Date(), "河南
省郑州市XXX区XX街XX路XX号"));
    System.out.println(user);
 }
  //==================================================================
  /**
  * 接口中声明方法查询:
  *  根据年龄区间查询数据 并根据年龄降序排列
  */
  @Test
  public void testQueryByRange(){
List<User> users = userRepository.findByAgeBetweenOrderByAgeDesc(20, 28);
    users.forEach(user -> System.out.println(user));
 }
  /**
  * 接口中声明方法查询:
  *  查询真实姓名已“王”开头的数据
  *
  *  响应结果:
  *  User{id='6', name='wb', realname='王八', age=26, salary=10000.0, birthday=Sat Dec 29
14:38:39 CST 2018, address='河南省郑州市XXX区XXX街XXX路XXX号'}
     User{id='3', name='ww', realname='王五', age=25, salary=4300.0, birthday=Tue Mar 15
08:00:00 CST 2016, address='北京市XXX区XXX村XXX街X商城XXX楼XXX室'}
  */
  @Test
  public void testQueryByPrefix(){
    List<User> users = userRepository.findByRealnameStartingWith("王");
    users.forEach(user -> System.out.println(user));
 }
 
  //==================================================================
  /**
  * 通过Query注解自定义查询表达式
  */
  @Test
  public void testQueryByNameLike(){
    List<User> users = userRepository.findByNameLike("zs");
    users.forEach(user -> System.out.println(user));
 }
}

2. 自定义Repository接口:使用 elasticsearchTemplate 实现复杂查询

自定义 CustomUserRepository 接口

import com.baizhi.entity.User;
import java.util.List;
import java.util.Map;
/**
* @author gaozhy
* @date 2019/1/1.23:10
*/
public interface CustomUserRepository {
	 public List<User> findByPageable(int nowPage,int pageSize);
	 public List<User> findByFieldDesc(String field);
	 public List<User> findByRealNameLikeAndHighLight(String realName);
	 public List<User> findByNameWithTermFilter(String ...terms);
	 public List<User> findByAgeWithRangeFilter(int start,int end);
	 public Map findByNameStartingWithAndAggregations(String prefixName);
	 /**
	 * 嵌套查询:
	 *
	 * 先按年龄直方图(桶聚合)统计
	 * 然后再统计区间内员工的最高工资(度量聚合)
	 */
	 public Map aggregationsWithHistogramAndMax();
	 /**
	 * 日期直方图(桶聚合)
	 */
	 public Map aggregationsWithDateHistogram();
}

自定义 CustomUserRepositoryImpl 实现类

import com.baizhi.entity.User;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogramInterval;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.ResultsExtractor;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.index.query.QueryBuilders.*;
/**
* @author gaozhy
* @date 2019/1/1.23:11
*/
public class CustomUserRepositoryImpl implements CustomUserRepository {
  @Autowired
  private ElasticsearchTemplate template;
  /**
  * ====================================
  * {
  * "query": {
  * "match_all": {}
  * },
  * "from":1,   //从第几条开始  (从0开始)
  * "size":1   //大小
  * }
  * ====================================
  *
  * @param nowPage
  * @param pageSize
  * @return
  */
  @Override
  public List<User> findByPageable(int nowPage, int pageSize) {
    SearchQuery query = new NativeSearchQueryBuilder()
       .withQuery(matchAllQuery())
       .withPageable(new PageRequest((nowPage - 1) * pageSize, pageSize))
       .build();
    return template.queryForList(query, User.class);
 }
  /**
   * @param field
   * @return
   */
  @Override
  public List<User> findByFieldDesc(String field) {
    SearchQuery query = new NativeSearchQueryBuilder()
       .withQuery(matchAllQuery())
       .withSort(SortBuilders.fieldSort(field).order(SortOrder.DESC))
       .build();
    return template.queryForList(query, User.class);
 }
  /**
  * 高亮
  *
  * @param realName
  * @return
  */
  @Override
  public List<User> findByRealNameLikeAndHighLight(String realName) {
    SearchQuery query = new NativeSearchQueryBuilder()
       			.withQuery(matchQuery("realname", realName))
       			.withHighlightFields(new HighlightBuilder.Field("realname"))
       			.build();
    AggregatedPage<User> users = template.queryForPage(query, User.class, new
SearchResultMapper() {
      @Override
      public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T>
aClass, Pageable pageable) {
        ArrayList<User> users = new ArrayList<>();
        SearchHits searchHits = searchResponse.getHits();
        for (SearchHit searchHit : searchHits) {
          if (searchHits.getHits().length <= 0) {
            return null;
         }
          User user = new User();
          user.setId(searchHit.getId());
          // searchHit.getSourceAsMap().forEach((k, v) -> System.out.println(k + " "
+ v));
          user.setName(searchHit.getSourceAsMap().get("name").toString());
          user.setAddress(searchHit.getSourceAsMap().get("address").toString());
        
 		  user.setAge(Integer.parseInt(searchHit.getSourceAsMap().get("age").toString()));
          user.setBirthday(new
Date(Long.parseLong(searchHit.getSourceAsMap().get("birthday").toString())));
        
 user.setSalary(Double.parseDouble(searchHit.getSourceAsMap().get("salary").toString()));
          String realname =
searchHit.getHighlightFields().get("realname").fragments()[0].toString();
          user.setRealname(realname);
          users.add(user);
       }
        return new AggregatedPageImpl<T>((List<T>) users);
     }
   });
    return users.getContent();
 }
  @Override
  public List<User> findByNameWithTermFilter(String... terms) {
    SearchQuery query = new NativeSearchQueryBuilder()
			       .withQuery(matchAllQuery())
			       .withFilter(termsQuery("name",terms))
			       .build();
    System.out.println(query.getFilter());
	return template.queryForList(query,User.class);
 }
  @Override
  public List<User> findByAgeWithRangeFilter(int start, int end) {
    SearchQuery query = new NativeSearchQueryBuilder()
			       .withFilter(rangeQuery("age").gte(start).lte(end))
			       .build();
    //System.out.println(query.getQuery());
    //System.out.println(query.getFilter());
    return template.queryForList(query,User.class);
 }
  @Override
  public Map<String, Aggregation> findByNameStartingWithAndAggregations(String prefixName) {
    SearchQuery query = new NativeSearchQueryBuilder()
       .withQuery(prefixQuery("name",prefixName))
        // result为度量聚合结果的别名
       .addAggregation(AggregationBuilders.avg("result").field("age"))
       .build();
    Aggregations aggregations = template.query(query, new ResultsExtractor<Aggregations>(){
      @Override
      public Aggregations extract(SearchResponse searchResponse) {
        Aggregations aggregations = searchResponse.getAggregations();
        return aggregations;
     }
   });
    Map<String, Aggregation> map = aggregations.getAsMap();
    return map;
 }
  @Override
  public Map aggregationsWithHistogramAndMax() {
    SearchQuery query = new NativeSearchQueryBuilder()
      
.addAggregation(AggregationBuilders.histogram("result").field("age").interval(5)
           .subAggregation(AggregationBuilders.max("max_salary").field("salary")))
       .build();
    Aggregations aggregations = template.query(query, new ResultsExtractor<Aggregations>(){
      @Override
      public Aggregations extract(SearchResponse searchResponse) {
        return searchResponse.getAggregations();
     }
   });
    return aggregations.getAsMap();
 }
  @Override
  public Map aggregationsWithDateHistogram() {
    SearchQuery query = new NativeSearchQueryBuilder()
    .addAggregation(AggregationBuilders.dateHistogram("result").field("birthday").format("yyyy-MM-
dd").dateHistogramInterval(DateHistogramInterval.YEAR))
       .build();
    Aggregations aggregations = template.query(query, new ResultsExtractor<Aggregations>(){
      @Override
      public Aggregations extract(SearchResponse searchResponse) {
        return searchResponse.getAggregations();
     }
   });
    return aggregations.getAsMap();
 }
}

将实现类注入到工厂

import com.dao.CustomUserRepositoryImpl ;
import com.dao.PoetryDao;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ImportUserRepository {

    @Bean
    public CustomUserRepositoryImpl getCustomUserRepositoryImpl (){
        return new CustomUserRepositoryImpl ();
    }
}

此处省略测试
以上就是ES JavaAPI的一般使用
描述略少,请看代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值