SpringBoot整合ElasticSearch

1 SpringBoot整合ElasticSearch

1.1 pom依賴和版本關(guān)系

1.1.1 pom.xml

導(dǎo)入elasticsearch依賴,在pom.xml里加入如下依賴

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

注意:檢查依賴版本是否與前所用的版本是否一致,如果不一致,會(huì)連接失敗

image.png

1.1.2 版本關(guān)系

SpringBoot 版本問(wèn)題尺碰,SpringBoot 的版本對(duì)應(yīng)不上ES的版本

Spring Data Release Train Spring Data Elasticsearch Elasticsearch Spring Framework Spring Boot
2021.2 (Raj) 4.4.x 7.17.9 5.3.x 2.7.x
2021.1 (Q) 4.3.x 7.15.2 5.3.x 2.6.x
2021.0 (Pascal) 4.2.x[1] 7.12.0 5.3.x 2.5.x
2020.0 (Ockham)[1] 4.1.x[1] 7.9.3 5.3.2 2.4.x
Neumann[1] 4.0.x[1] 7.6.2 5.2.12 2.3.x
Moore[1] 3.2.x[1] 6.8.12 5.2.12 2.2.x
Lovelace[1] 3.1.x[1] 6.2.2 5.1.19 2.1.x
Kay[1] 3.0.x[1] 5.5.0 5.0.13 2.0.x
Ingalls[1] 2.1.x[1] 2.4.0 4.3.25 1.5.x

由于以上ElasticSearch 版本之間的差距導(dǎo)致對(duì)應(yīng)Spring Data ElasticSearch包的差距糙麦;所以在不降低 Spring Boot 版本的情況需兼容低版本的 ElasticSearch 的客戶端。

解決方法:

  • 方案一
    由于不兼容厨疙,即放棄 Spring Data ElasticSearch 框架包,使用最直接的 Java ElasticSearch Client 連接即可疑务,將 Client 注入到 Spring 容器中沾凄,使用High/Low Level Client API連接也是可以的(HighLevel 是在 LowLevel Client 的基礎(chǔ)上封裝而成的)
    點(diǎn)擊查看JavaAPI操作ES
  • 方案二
    由于 SpringBoot 2.3.x 以上版本只支持 ES7 服務(wù)梗醇,所以對(duì)于一些本身為SpringBoot 高版本的項(xiàng)目而言單純的引入spring-boot-starter-data-elasticsearch 模塊包是存在兼容性問(wèn)題的,所以需要將 Spring Data ElasticSearch 單獨(dú)引入撒蟀,由于ES6對(duì)應(yīng)的 Spring Data ElasticSearch 為3.2.x 版本

1.2 創(chuàng)建客戶端

1.2.1 高級(jí)客戶端

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ElasticSearchClientConfig {
    @Bean
    public RestHighLevelClient restHighLevelClient(){
        RestHighLevelClient client = new RestHighLevelClient(
                RestClient.builder(
                        new HttpHost("服務(wù)器IP", 9200, "http")));
        return client;
    }
}

1.2.2 ES 8.0后客戶端

@ConfigurationProperties(prefix = "elasticsearch")
@Configuration
@Data
public class ElasticsearchConfig {
    //多個(gè)IP逗號(hào)隔開
    private String hosts;
    private String username;
    private String password;



    /**
     * 同步方式
     */
    @Bean
    public ElasticsearchClient elasticsearchClient() {
        HttpHost[] httpHosts = toHttpHost();
        // 用戶認(rèn)證對(duì)象
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        // 設(shè)置賬號(hào)密碼
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));

        // Create the RestClient
        RestClient restClient = RestClient.builder(httpHosts).setHttpClientConfigCallback(hp -> {
            //es 毙鸾鳎活,可以確保每次連接不是重新建立tcp 連接
            hp.setKeepAliveStrategy((response, context) ->  Duration.ofMinutes(5).toMillis());
            hp.disableAuthCaching();

            hp.setDefaultCredentialsProvider(credentialsProvider);
            return hp;
        }).build();
        // Create the transport with a Jackson mapper
        RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        // create the API client
        return new ElasticsearchClient(transport);
    }
    /**
     * 異步方式
     */
    public ElasticsearchAsyncClient elasticsearchAsyncClient() {
        HttpHost[] httpHosts = toHttpHost();
        RestClient restClient = RestClient.builder(httpHosts).build();
        RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        return new ElasticsearchAsyncClient(transport);
    }
    /**
     * 解析配置的字符串hosts牙肝,轉(zhuǎn)為HttpHost對(duì)象數(shù)組
     */
    private HttpHost[] toHttpHost() {
        if (!StringUtils.hasLength(hosts)) {
            throw new RuntimeException("invalid elasticsearch configuration. elasticsearch.hosts is null");
        }
        // 多個(gè)IP逗號(hào)隔開
        String[] hostArray = hosts.split(",");
        HttpHost[] httpHosts = new HttpHost[hostArray.length];
        HttpHost httpHost;
        for (int i = 0; i < hostArray.length; i++) {
            String[] strings = hostArray[i].split(":");
            httpHost = new HttpHost(strings[0], Integer.parseInt(strings[1]), "http");
            httpHosts[i] = httpHost;
        }
        return httpHosts;
    }
}

使用時(shí)注入 ElasticsearchClient 即可

@Autowired
private ElasticsearchClient elasticsearchClient;

注意ES8.0后推薦用 ElasticsearchClient唉俗,而不是 RestHighLevelClient

1.3 基本用法

1.3.1 創(chuàng)建、判斷存在配椭、刪除索引

import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;

@SpringBootTest
public class ElasticsearchApplicationTests {

 @Autowired
 private RestHighLevelClient restHighLevelClient;

 @Test
 void testCreateIndex() throws IOException {
  //1.創(chuàng)建索引請(qǐng)求
  CreateIndexRequest request = new CreateIndexRequest("ljx666");
  //2.客戶端執(zhí)行請(qǐng)求IndicesClient虫溜,執(zhí)行create方法創(chuàng)建索引,請(qǐng)求后獲得響應(yīng)
  CreateIndexResponse response=
    restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
  System.out.println(response);
 }

 @Test
 void testExistIndex() throws IOException {
        //1.查詢索引請(qǐng)求
  GetIndexRequest request=new GetIndexRequest("ljx666");
        //2.執(zhí)行exists方法判斷是否存在
  boolean exists=restHighLevelClient.indices().exists(request,RequestOptions.DEFAULT);
  System.out.println(exists);
 }

 @Test
 void testDeleteIndex() throws IOException {
        //1.刪除索引請(qǐng)求
  DeleteIndexRequest request=new DeleteIndexRequest("ljx666");
        //執(zhí)行delete方法刪除指定索引
  AcknowledgedResponse delete = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
  System.out.println(delete.isAcknowledged());
 }

}

1.3.2 對(duì)文檔的CRUD

創(chuàng)建文檔
注意:如果添加時(shí)不指定文檔ID股缸,他就會(huì)隨機(jī)生成一個(gè)ID衡楞,ID唯一。
創(chuàng)建文檔時(shí)若該ID已存在敦姻,發(fā)送創(chuàng)建文檔請(qǐng)求后會(huì)更新文檔中的數(shù)據(jù)瘾境。

@Test
void testAddUser() throws IOException {
 //1.創(chuàng)建對(duì)象
 User user=new User("Go",21,new String[]{"內(nèi)卷","吃飯"});
 //2.創(chuàng)建請(qǐng)求
 IndexRequest request=new IndexRequest("ljx666");
 //3.設(shè)置規(guī)則 PUT /ljx666/_doc/1
 //設(shè)置文檔id=6,設(shè)置超時(shí)=1s等镰惦,不設(shè)置會(huì)使用默認(rèn)的
 //同時(shí)支持鏈?zhǔn)骄幊倘?request.id("6").timeout("1s");
 request.id("6");
 request.timeout("1s");

 //4.將數(shù)據(jù)放入請(qǐng)求迷守,要將對(duì)象轉(zhuǎn)化為json格式
    //XContentType.JSON,告訴它傳的數(shù)據(jù)是JSON類型
 request.source(JSONValue.toJSONString(user), XContentType.JSON);
    
 //5.客戶端發(fā)送請(qǐng)求旺入,獲取響應(yīng)結(jié)果
 IndexResponse indexResponse=restHighLevelClient.index(request,RequestOptions.DEFAULT);
 System.out.println(indexResponse.toString());
 System.out.println(indexResponse.status());
}

獲取文檔中的數(shù)據(jù):

@Test
void testGetUser() throws IOException {
 //1.創(chuàng)建請(qǐng)求,指定索引兑凿、文檔id
 GetRequest request=new GetRequest("ljx666","1");
 GetResponse getResponse=restHighLevelClient.get(request,RequestOptions.DEFAULT);
  
 System.out.println(getResponse);//獲取響應(yīng)結(jié)果
 //getResponse.getSource() 返回的是Map集合
 System.out.println(getResponse.getSourceAsString());//獲取響應(yīng)結(jié)果source中內(nèi)容,轉(zhuǎn)化為字符串
  
}

更新文檔數(shù)據(jù):
注意:需要將User對(duì)象中的屬性全部指定值茵瘾,不然會(huì)被設(shè)置為空礼华,如User只設(shè)置了名稱,那么只有名稱會(huì)被修改成功拗秘,其他會(huì)被修改為null圣絮。

@Test
void testUpdateUser() throws IOException {
 //1.創(chuàng)建請(qǐng)求,指定索引、文檔id
 UpdateRequest request=new UpdateRequest("ljx666","6");

 User user =new User("GoGo",21,new String[]{"內(nèi)卷","吃飯"});
 //將創(chuàng)建的對(duì)象放入文檔中
 request.doc(JSONValue.toJSONString(user),XContentType.JSON);

 UpdateResponse updateResponse=restHighLevelClient.update(request,RequestOptions.DEFAULT);
 System.out.println(updateResponse.status());//更新成功返回OK
}

刪除文檔:

@Test
void testDeleteUser() throws IOException {
 //創(chuàng)建刪除請(qǐng)求雕旨,指定要?jiǎng)h除的索引與文檔ID
 DeleteRequest request=new DeleteRequest("ljx666","6");

 DeleteResponse updateResponse=restHighLevelClient.delete(request,RequestOptions.DEFAULT);
 System.out.println(updateResponse.status());//刪除成功返回OK扮匠,沒(méi)有找到返回NOT_FOUND
}

1.3.3 批量CRUD數(shù)據(jù)

這里只列出了批量插入數(shù)據(jù),其他與此類似

注意hasFailures()方法是返回是否失敗奸腺,即它的值為false時(shí)說(shuō)明上傳成功

@Test
void testBulkAddUser() throws IOException {
 BulkRequest bulkRequest=new BulkRequest();
 //設(shè)置超時(shí)
 bulkRequest.timeout("10s");

 ArrayList<User> list=new ArrayList<>();
 list.add(new User("Java",25,new String[]{"內(nèi)卷"}));
 list.add(new User("Go",18,new String[]{"內(nèi)卷"}));
 list.add(new User("C",30,new String[]{"內(nèi)卷"}));
 list.add(new User("C++",26,new String[]{"內(nèi)卷"}));
 list.add(new User("Python",20,new String[]{"內(nèi)卷"}));

 int id=1;
 //批量處理請(qǐng)求
 for (User u :list){
  //不設(shè)置id會(huì)生成隨機(jī)id
  bulkRequest.add(new IndexRequest("ljx666")
    .id(""+(id++))
    .source(JSONValue.toJSONString(u),XContentType.JSON));
 }

 BulkResponse bulkResponse=restHighLevelClient.bulk(bulkRequest,RequestOptions.DEFAULT);
 System.out.println(bulkResponse.hasFailures());//是否執(zhí)行失敗,false為執(zhí)行成功
}

1.3.4 查詢所有餐禁、模糊查詢、分頁(yè)查詢突照、排序、高亮顯示

@Test
void testSearch() throws IOException {
 SearchRequest searchRequest=new SearchRequest("ljx666");//里面可以放多個(gè)索引
 SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();//構(gòu)造搜索條件

 //此處可以使用QueryBuilders工具類中的方法
 //1.查詢所有
 sourceBuilder.query(QueryBuilders.matchAllQuery());
 //2.查詢name中含有Java的
 sourceBuilder.query(QueryBuilders.multiMatchQuery("java","name"));
 //3.分頁(yè)查詢
 sourceBuilder.from(0).size(5);
    
 //4.按照score正序排列
 //sourceBuilder.sort(SortBuilders.scoreSort().order(SortOrder.ASC));
 //5.按照id倒序排列(score會(huì)失效返回NaN)
 //sourceBuilder.sort(SortBuilders.fieldSort("_id").order(SortOrder.DESC));

 //6.給指定字段加上指定高亮樣式
 HighlightBuilder highlightBuilder=new HighlightBuilder();
 highlightBuilder.field("name").preTags("<span style='color:red;'>").postTags("</span>");
 sourceBuilder.highlighter(highlightBuilder);
  
 searchRequest.source(sourceBuilder);
 SearchResponse searchResponse=restHighLevelClient.search(searchRequest,RequestOptions.DEFAULT);

 //獲取總條數(shù)
 System.out.println(searchResponse.getHits().getTotalHits().value);
 //輸出結(jié)果數(shù)據(jù)(如果不設(shè)置返回條數(shù)氧吐,大于10條默認(rèn)只返回10條)
 SearchHit[] hits=searchResponse.getHits().getHits();
 for(SearchHit hit :hits){
  System.out.println("分?jǐn)?shù):"+hit.getScore());
  Map<String,Object> source=hit.getSourceAsMap();
  System.out.println("index->"+hit.getIndex());
  System.out.println("id->"+hit.getId());
  for(Map.Entry<String,Object> s:source.entrySet()){
   System.out.println(s.getKey()+"--"+s.getValue());
  }
 }
}

1.4 高階用法

1.4.1 精確查詢

1.4.1.1 單條件精確查詢

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 單條件精確查詢
     * @throws IOException
     */
    @Test
    public void search0() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.termsQuery("name", "趙里"));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }

}

1.4.1.2 根據(jù) id 精確匹配

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 根據(jù)id精確匹配
     * @throws IOException
     */
    @Test
    public void searchById() throws IOException {
        String[] ids = new String[]{"1","2"};
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.termsQuery("_id", ids));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.2 多條件精確查詢讹蘑,取并集

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 多條件精確查詢末盔,取并集
     * @throws IOException
     */
    @Test
    public void search1() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.termsQuery("name", "張", "陳"));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.3 范圍查詢

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 范圍查詢,包括from座慰、to
     * @throws IOException
     */
    @Test
    public void search2() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.rangeQuery("age").from(20).to(32));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }


    /**
     * 范圍查詢陨舱,不包括from、to
     * @throws IOException
     */
    @Test
    public void search3() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.rangeQuery("age").from(20,false).to(30, false));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }


    /**
     * 范圍查詢, lt:小于版仔,gt:大于
     * @throws IOException
     */
    @Test
    public void search4() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.rangeQuery("age").lt(30).gt(20));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.4 模糊查詢游盲,支持通配符

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 模糊查詢,支持通配符
     * @throws IOException
     */
    @Test
    public void search5() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.wildcardQuery("name","張三"));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }

}

1.4.5 不使用通配符的模糊查詢蛮粮,左右匹配

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 不使用通配符的模糊查詢益缎,左右匹配
     * @throws IOException
     */
    @Test
    public void search6() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.queryStringQuery("張三").field("name"));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.6 多字段模糊查詢

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 多字段模糊查詢
     * @throws IOException
     */
    @Test
    public void search7() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.multiMatchQuery("長(zhǎng)", "name", "city"));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.7 分頁(yè)+排序 查詢

1.4.7.1 分頁(yè)

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 分頁(yè)搜索
     * @throws IOException
     */
    @Test
    public void search8() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .from(0).size(2);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }

}

1.4.7.2 排序查詢

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 排序,字段的類型必須是:integer然想、double莺奔、long或者keyword
     * @throws IOException
     */
    @Test
    public void search9() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .sort("createTime", SortOrder.ASC);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }

}

1.4.7.3 分頁(yè)+排序

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 多條件查詢 + 排序 + 分頁(yè)
     * @throws IOException
     */
    @Test
    public void search29() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //條件搜索
        BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.matchQuery("name", "張王"));
        boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(30).gte(20));
        builder.query(boolQueryBuilder);

        //結(jié)果集合分頁(yè)
        builder.from(0).size(2);

        //排序
        builder.sort("createTime",SortOrder.ASC);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.8 精確統(tǒng)計(jì)篩選文檔數(shù)

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 精確統(tǒng)計(jì)篩選文檔數(shù),查詢性能有所降低
     * @throws IOException
     */
    @Test
    public void search10() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .trackTotalHits(true);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }

}

1.4.9 設(shè)置源字段過(guò)濾返回

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 設(shè)置源字段過(guò)慮,第一個(gè)參數(shù)結(jié)果集包括哪些字段,第二個(gè)參數(shù)表示結(jié)果集不包括哪些字段
     * @throws IOException
     */
    @Test
    public void search11() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .fetchSource(new String[]{"name","age","city","createTime"},new String[]{});

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.10 match 搜索匹配

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * match搜索匹配
     * @throws IOException
     */
    @Test
    public void search22() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder()
                .query(QueryBuilders.matchQuery("name", "張王"));

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.11 bool組合查詢

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * bool組合查詢
     * @throws IOException
     */
    @Test
    public void search23() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder();

        BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.matchQuery("name", "張王"));
        boolQueryBuilder.must(QueryBuilders.rangeQuery("age").lte(30).gte(20));
        builder.query(boolQueryBuilder);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.12 nested 類型嵌套查詢

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * nested類型嵌套查詢
     * @throws IOException
     */
    @Test
    public void search24() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //條件查詢
        BoolQueryBuilder mainBool=new BoolQueryBuilder();
        mainBool.must(QueryBuilders.matchQuery("name", "趙六"));

        //nested類型嵌套查詢
        BoolQueryBuilder boolQueryBuilder=new BoolQueryBuilder();
        boolQueryBuilder.must(QueryBuilders.matchQuery("products.brand", "A"));
        boolQueryBuilder.must(QueryBuilders.matchQuery("products.title", "巧克力"));
        NestedQueryBuilder nested = QueryBuilders.nestedQuery("products",boolQueryBuilder, ScoreMode.None);
        mainBool.must(nested);

        builder.query(mainBool);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.13 聚合查詢

1.4.13.1 求和

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 聚合查詢 sum
     * @throws IOException
     */
    @Test
    public void search30() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //條件搜索
        builder.query(QueryBuilders.matchAllQuery());
        //聚合查詢
        AggregationBuilder aggregation = AggregationBuilders.sum("sum_age").field("age");
        builder.aggregation(aggregation);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.13.2 求平均值

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 聚合查詢 avg
     * @throws IOException
     */
    @Test
    public void search31() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //條件搜索
        builder.query(QueryBuilders.matchAllQuery());
        //聚合查詢
        AggregationBuilder aggregation = AggregationBuilders.avg("avg_age").field("age");
        builder.aggregation(aggregation);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.13.3 計(jì)數(shù)

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 聚合查詢 count
     * @throws IOException
     */
    @Test
    public void search32() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //條件搜索
        builder.query(QueryBuilders.matchAllQuery());
        //聚合查詢
        AggregationBuilder aggregation = AggregationBuilders.count("count_age").field("age");
        builder.aggregation(aggregation);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

1.4.13.4 分組

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticSearchApplication.class)
public class SearchJunit {

    @Autowired
    private RestHighLevelClient client;

    /**
     * 聚合查詢 分組
     * @throws IOException
     */
    @Test
    public void search33() throws IOException {
        // 創(chuàng)建請(qǐng)求
        SearchSourceBuilder builder = new SearchSourceBuilder();

        //條件搜索
        builder.query(QueryBuilders.matchAllQuery());
        //聚合查詢
        AggregationBuilder aggregation = AggregationBuilders.terms("tag_createTime").field("createTime")
                .subAggregation(AggregationBuilders.count("count_age").field("age")) //計(jì)數(shù)
                .subAggregation(AggregationBuilders.sum("sum_age").field("age")) //求和
                .subAggregation(AggregationBuilders.avg("avg_age").field("age")); //求平均值

        builder.aggregation(aggregation);

        //不輸出原始數(shù)據(jù)
        builder.size(0);

        //搜索
        SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices("cs_index");
        searchRequest.types("_doc");
        searchRequest.source(builder);
        // 執(zhí)行請(qǐng)求
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        // 解析查詢結(jié)果
        System.out.println(response.toString());
    }
}

參考鏈接:https://mp.weixin.qq.com/s/F-eleu11MZLDiGpHfECdRg

1.5 總結(jié)

  1. 大致流程
    創(chuàng)建對(duì)應(yīng)的請(qǐng)求 --> 設(shè)置請(qǐng)求(添加規(guī)則变泄,添加數(shù)據(jù)等) --> 執(zhí)行對(duì)應(yīng)的方法(傳入請(qǐng)求令哟,默認(rèn)請(qǐng)求選項(xiàng))–> 接收響應(yīng)結(jié)果(執(zhí)行方法返回值)–> 輸出響應(yīng)結(jié)果中需要的數(shù)據(jù)(source,status等)
  2. 注意事項(xiàng)
    如果不指定id妨蛹,會(huì)自動(dòng)生成一個(gè)隨機(jī)id
    正常情況下屏富,不應(yīng)該這樣使用new IndexRequest(“l(fā)jx777”),如果索引發(fā)生改變了蛙卤,那么代碼都需要修改狠半,可以定義一個(gè)枚舉類或者一個(gè)專門存放常量的類,將變量用final static等進(jìn)行修飾表窘,并指定索引值典予。其他地方引用該常量即可,需要修改也只需修改該類即可乐严。
    elasticsearch相關(guān)的東西瘤袖,版本都必須一致,不然會(huì)報(bào)錯(cuò)
    elasticsearch很消耗內(nèi)存昂验,建議在內(nèi)存較大的服務(wù)器上運(yùn)行elasticsearch捂敌,否則會(huì)因?yàn)閮?nèi)存不足導(dǎo)致elasticsearch自動(dòng)killed

轉(zhuǎn)載于:https://mp.weixin.qq.com/s/G8x18bvHQz60gGu1YiRJ5w

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市既琴,隨后出現(xiàn)的幾起案子占婉,更是在濱河造成了極大的恐慌,老刑警劉巖甫恩,帶你破解...
    沈念sama閱讀 211,639評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逆济,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)奖慌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門抛虫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人简僧,你說(shuō)我怎么就攤上這事建椰。” “怎么了岛马?”我有些...
    開封第一講書人閱讀 157,221評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵棉姐,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我啦逆,道長(zhǎng)伞矩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,474評(píng)論 1 283
  • 正文 為了忘掉前任蹦浦,我火速辦了婚禮扭吁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘盲镶。我一直安慰自己侥袜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,570評(píng)論 6 386
  • 文/花漫 我一把揭開白布溉贿。 她就那樣靜靜地躺著枫吧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宇色。 梳的紋絲不亂的頭發(fā)上九杂,一...
    開封第一講書人閱讀 49,816評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音宣蠕,去河邊找鬼例隆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛抢蚀,可吹牛的內(nèi)容都是我干的镀层。 我是一名探鬼主播,決...
    沈念sama閱讀 38,957評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼皿曲,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼唱逢!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起屋休,我...
    開封第一講書人閱讀 37,718評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤坞古,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后劫樟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體痪枫,經(jīng)...
    沈念sama閱讀 44,176評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡织堂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,511評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了听怕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弄兜。...
    茶點(diǎn)故事閱讀 38,646評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡十气,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蝗敢,到底是詐尸還是另有隱情翅睛,我是刑警寧澤声搁,帶...
    沈念sama閱讀 34,322評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站捕发,受9級(jí)特大地震影響疏旨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扎酷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,934評(píng)論 3 313
  • 文/蒙蒙 一檐涝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧法挨,春花似錦谁榜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至荐糜,卻和暖如春巷怜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背暴氏。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工延塑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人答渔。 一個(gè)月前我還...
    沈念sama閱讀 46,358評(píng)論 2 360
  • 正文 我出身青樓关带,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親研儒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子豫缨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,514評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容