SpringBoot中Elasticsearch客户端及API使用

官方文档:Java Transport Client (deprecated) [7.17] | Elastic

1.创建客户端

(1)TransportClient

在ES 7.0版本中将弃用TransportClient客户端,且在8.0版本中完全移除它

创建步骤:

//直接在http://127.0.0.1:9200/ 中可以看到es对应的cluster_name
Settings settings= Settings.builder()
    .put("cluster.name","这里是es对应的cluster_name").build(); 
TransportClient transportClient=new PreBuiltTransportClient(settings);
transportClient.addTransportAddress(new 
          TransportAddress(InetAddress.getByName("127.0.0.1"),9300));

然后就可以通过transportClient来进行es的操作了。

(2)RestHighLevelClient

还有对应的RestLowLevelClient低级客户端不过没有多少使用者。

RestHighLevelClient是官方新推出的,使用Http连接查询结果,因此需要9200端口。是RestFul风格

RestHighLevelClient restHighLevelClient(){
    RestHighLevelClient client = new RestHighLevelClient(
        RestClient.builder(
            new HttpHost("127.0.0.1", 9200, "http")));
    return client;
}

然后就可以通过client来进行es的操作了。

以上是最长用的两个客户端。

(3)Jest

Github: GitHub - searchbox-io/Jest: Elasticsearch Java Rest Client.

如果在项目中使用了不同版本的ES集群,那么使用原生的客户端那么会是一个问题。如果ES的版本不是问题,那么还是建议使用原生的客户端会更好一些。 ES没有Rest客户端,所以Jest出现的原因。

Maven Repository: Index of /groups/public/io/searchbox/jest 从 5.x 版本开始最低要求使用JDK8

/**
     * 简单构建一个 Jestclient
     *
     * @param serverList es集群机器列表,每一台机器形如: http://xxx.xxx.xxx:9200
     * @return
     */
public static JestHttpClient getJestHttpClient(List serverList) {
    JestClientFactory jestClientFactory = new JestClientFactory();
​
    HttpClientConfig.Builder httpClientConfigBuilder = new                                          HttpClientConfig.Builder(serverList);
​
    jestClientFactory.setHttpClientConfig(httpClientConfigBuilder.build());
​
    JestHttpClient jestHttpClient = (JestHttpClient) jestClientFactory.getObject();
​
    return jestHttpClient;
}

HttpClientConfig

参数 说明 备注
serverList ES集群机器列表
isMultiThreaded 是否使用HttpClient连接池
isDiscoveryEnabled 是否开启节点侦测 建议使用该参数,当集群中机器下线,可以检测到并更新机器列表
discoveryFilter
isRequestCompressionEnabled 是否开启GZIP压缩请求 需要ES节点设置 http.compression
connTimeout HttpClient的connTimeout
readTimeout HttpClient的readTimeout
discoveryFrequency 节点侦测的频率
maxConnectionIdleTime
discoveryFrequencyTimeUnit 节点侦测的频率单位 TimeUnit
maxConnectionIdleTimeDurationTimeUnit
gson
defaultSchemeForDiscoveredNodes
maxTotalConnection HttpClient连接池的最大连接数
defaultMaxTotalConnectionPerRoute HttpClient连接池每个路由的默认最大连接数
maxTotalConnectionPerRoute HttpClient连接池路由的最大连接数 会覆盖defaultMaxTotalConnectionPerRoute的默认值
credentialsProvider
sslSocketFactory
plainSocketFactory
httpRoutePlanner
proxyAuthenticationStrategy
httpIOSessionStrategy
httpsIOSessionStrategy
preemptiveAuthTargetHosts

2.SearchRequest,BulkRequest..

都是建立在RestHighLevelClient高级restful风格客户端的前提下。取得上方的client

@Autowired
    private RestHighLevelClient restHighLevelClient;
​
    //PUT testCreate
    @Test
    void testCreate() throws IOException {
        //1.创建索引请求
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("test_create");
        //2.执行创建请求    IndicesClient,请求后获得响应
        CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
        System.out.println(createIndexResponse);
    }
​
    //测试获取索引,判断其是否存在
    @Test
    void getEs() throws IOException {
        GetIndexRequest test_create = new GetIndexRequest("test_create");
        boolean exists = restHighLevelClient.indices().exists(test_create, RequestOptions.DEFAULT);
        System.out.println(exists);
    }
​
    //测试删除索引
    @Test
    void deleteEs() throws IOException {
        DeleteIndexRequest test_create = new DeleteIndexRequest("test_create");
        AcknowledgedResponse delete = restHighLevelClient.indices().delete(test_create, RequestOptions.DEFAULT);
        System.out.println(delete);
    }
​
    //测试添加文档
    @Test
    void AddEsWd() throws IOException {
        //创建实体类对象
        User user = new User("我是测试集成java",12);
        //创建请求
        IndexRequest test_create = new IndexRequest("test_create");
        //创建规则
        test_create.id("1");
        test_create.timeout(TimeValue.timeValueSeconds(1));
        //超出1s就不执行
        test_create.timeout("1s");
        //将数据放入请求 这里使用fastjson,不过推荐使用hutoool工具类
        IndexRequest source = test_create.source(JSON.toJSONString(user), XContentType.JSON);
        //客户端发送请求
        IndexResponse index = restHighLevelClient.index(source, RequestOptions.DEFAULT);
        //获取相应的结果
        System.out.println(index.toString());   //IndexResponse[index=test_create,type=_doc,id=1,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
        System.out.println(index.status()); //CREATED
    }
​
    //测试获取文档
    @Test
    void getWd() throws IOException {
        GetRequest test_create = new GetRequest("test1", "1");
        //不获取返回的_source上下文效率更高
        test_create.fetchSourceContext(new FetchSourceContext(false));
        test_create.storedFields("_none_");
​
        boolean exists = restHighLevelClient.exists(test_create, RequestOptions.DEFAULT);
        System.out.println(exists);
    }
​
    //测试获取文档的信息
    @Test
    void getWdXx() throws IOException {
        GetRequest test_create = new GetRequest("test_create", "1");
        GetResponse exists = restHighLevelClient.get(test_create, RequestOptions.DEFAULT);
        System.out.println(exists);//返回全部的内容
        System.out.println(exists.getSource());//获取source中的信息 {name=我是测试集成java, age=12}
        System.out.println(exists.getVersion());//获取版本
        System.out.println(exists.getSourceAsString());//打印文档的内容 {"age":12,"name":"我是测试集成java"}
    }
​
    //更新文档的信息
    @Test
    void updateWdXx() throws IOException {
        UpdateRequest test_create = new UpdateRequest("test_create","1");
        User user = new User("更新测试", 12);
        test_create.doc(JSON.toJSONString(user),XContentType.JSON);
        UpdateResponse update = restHighLevelClient.update(test_create, RequestOptions.DEFAULT);
        System.out.println(update);
    }
​
    //删除文档记录
    @Test
    void deleteWdXx() throws IOException {
        DeleteRequest test_create = new DeleteRequest("test_create", "1");
        DeleteResponse delete = restHighLevelClient.delete(test_create, RequestOptions.DEFAULT);
        System.out.println(delete);
    }
​
    //真实的项目需要批量的插入数据
    @Test
    void testBulkRequest() throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        bulkRequest.timeout("10s");
        ArrayList users = new ArrayList<>();
        users.add(new User("test1",1));
        users.add(new User("test2",2));
        users.add(new User("test3",3));
        users.add(new User("test4",4));
        users.add(new User("test5",5));
        //批处理请求
        int i = 1;
        for (User user : users){
            i++;
            bulkRequest.add(new IndexRequest("test_create")
                    .id(""+i) //不写id的话就会生出随机的id
                    .source(JSON.toJSONString(user),XContentType.JSON));
        }
        BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
        System.out.println(bulk);
        System.out.println(bulk.hasFailures());//是否失败 false成功
    }
​
    //查询
    @Test
    void testSearch() throws IOException {
        SearchRequest searchRequest = new SearchRequest("test_create");
        //构建搜索的条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //创建一个query构造器,进行分组查询
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("name","test");
        searchSourceBuilder.query(matchQueryBuilder);
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        //RequestOptions.DEFAULT默认值
        SearchResponse search = restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);
        System.out.println(search.getHits());
        System.out.println("=======================");
        for (SearchHit hit : search.getHits()){
            System.out.println(hit.getSourceAsString());
        }
    }

3.ElasticsearchRepository

TransportClient客户端进行使用,RestHighLevelClient没测试过应该也可以。

es操作引用库。

T代表的是索引对应的实体类,其中存放索引中需要返回的字段和对应的getset方法和有参和无参构造方法。

可以直接使用lombok中的注解添加相应的getset和构造方法

import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
​
@Getter
@Setter
@ToString
@AllArgsConstructor     //有参
@NoArgsConstructor      //无参
//@Document(indexName = "test", type = "_doc")
@Document(indexName = "索引名称", type = "类型")
public class test implements Serializable {
    @Id
    private String id;// 索引中的主键id
​
    private String name; 
​
    private Date birthday;
}

然后再创建一个dao层实现ElasticsearchRepository

重写需要用到的方法即可使用service中调用dao层中方法来进行相应的搜索。

import com.hyq.test;
import org.elasticsearch.index.query.QueryBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
​
import java.util.Optional;
​
public interface test extends ElasticsearchRepository {
    @Override
    public Iterable findAll();
​
    @Override
    Optional findById(String s);
​
    @Override
    void deleteById(String s);
​
    @Override
    void deleteAll(Iterable entities);
​
    @Override
    void deleteAll();
​
    @Override
    Page search(SearchQuery searchQuery);
​
    @Override
    Page search(QueryBuilder queryBuilder, Pageable pageable);
​
}

类如Page search(QueryBuilder queryBuilder, Pageable pageable);

就可以在业务层调用。然后使用**QueryBuilder(BoolQueryBuilder ,MatchQueryBuilder ..)进行查询逻辑的编写。并设置Pageable进行分页和排序。将这两个参数传入即可得到查询的结果。

4.QueryBuilder

常用方法:

//进行单个值得精确匹配termQuery("key", obj) 完全匹配
QueryBuilders.termQuery("name","我是中国人")
    
//进行模糊查询multiMatchQuery("key.keyword", "*field1*"); 可以使用通配符.keyword是否添加查看上方的    Es的常见问题
QueryBuilders.wildcardQuery("name"/"name.keyword","*我是中*")
    
//进行多个值得精确匹配termsQuery("key", obj1, obj2..)   一次匹配多个值
String[] a = {"a","ab","ac","qq"}
QueryBuilders.termsQuery("name",a)
    
//模糊查询  和wildcardQuery对比的话不能使用通配符
QueryBuilders.matchQuery("name","我是")
    
//matchPhraseQuery对中文精确匹配
queryBuilders.matchPhraseQuery("key", value)
    
//进行布尔查询
QueryBuilders.boolQuery()
    
//进行模糊查询
QueryBuilders.boolQuery()
    
//进行范围查询 gte大于等于,lte小于等于 gt大于 lt小于
QueryBuilders.rangeQuery("age")
    .gte(jsonObjectEq.get("1"))
    .lte(jsonObjectEq.get("10")))
......

(1)BoolQueryBuilder

可以进行多条件判断查询

BoolQueryBuilder builder = QueryBuilders.boolQuery();
//must其中的条件必须满足 and
builder.must(queryBuilders.matchPhraseQuery("key", value));
//mustNot其中的条件必须不满足 not
builder.mustNot(queryBuilders.matchPhraseQuery("key", value));
//should其中的条件满足一个即可 or
builder.should(queryBuilders.matchPhraseQuery("key", value));
builder.should(QueryBuilders.matchQuery("name","我是"));

当同时使用must和should时,minumum_should_match默认是0。所以should就不会生效。

boolQueryBuilder.minimumShouldMatch(1)将其修改为1就可以解决这个问题。

然后再将其放置到NativeSearchQueryBuilder.withQuery(builder)。使用NativeSearchQueryBuilder进行更复杂的查询。

(2)NativeSearchQueryBuilder

NativeSearchQuery是一个原生的查询条件类,用来和ES的一些原生查询方法进行搭配,实现一些比较复杂的查询。

NativeSearchQueryBuilder可以进行复杂的查询设置。

 NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        //将搜索条件设置到构建中
        nativeSearchQueryBuilder.withQuery(builder);
        //将分页设置到构建中
        nativeSearchQueryBuilder.withPageable(page);
        //将排序设置到构建中(本人尝试不太好使,不如直接在Pageable中设置再放置到上方的分页中)
        nativeSearchQueryBuilder.withSort(sort);
        //生产NativeSearchQuery
        NativeSearchQuery query = nativeSearchQueryBuilder.build();

然后将query放入search方法或者SearchRequestBuilder.query()中...。进行复制查询并获得对应的返回结果。

5.Pageable

主要使用它的实现类PageRequest。

import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
​
//page为当前的页数,length为一页多少数据,sort为排序(详情见下一节)
Pageable page1 = PageRequest.of(page, length, sort);
//也可以不设置排序
Pageable page1 = PageRequest.of(page, length);

6.Sort

import org.springframework.data.domain.Sort;
​
Sort sort = Sort.by(Sort.Direction.ASC,"需要排序的字段");
Sort sort = Sort.by(Sort.Direction.DESC,"update_time")

你可能感兴趣的:(Elasticsearch,elasticsearch,spring,boot,java)