elasticsearch-java客户端测试

(1)添加依赖

    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.elasticsearch</groupId>
        <artifactId>elasticsearch</artifactId>
    </dependency>

(2)配置文件

application.yml

server:
  port: ${port:40100}
spring:
  application: service-search
elasticsearch: 
  hostlist: 
    - 127.0.0.1:9200 #多个节点中间用逗号分隔[addr1,addr2]
      

(3)创建配置类

package com.search.config;

import java.util.ArrayList;
import java.util.List;

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

import lombok.Getter;
import lombok.Setter;

@Configuration
@ConfigurationProperties(prefix="elasticsearch")
@Getter
@Setter
public class ElasticSearchConfig {

    
    private List<String> hostlist;
    
    @Bean
    public RestHighLevelClient restHighLevelClient(){
        List<HttpHost> httpHostList = new ArrayList<>(hostlist.size());
        //封装es服务端地址
        for(String host:hostlist){
            HttpHost httpHost = new HttpHost(host.split(":")[0], Integer.parseInt(host.split(":")[1]), "http");
            httpHostList.add(httpHost);
        }
        return new RestHighLevelClient(RestClient.builder(httpHostList.toArray(new HttpHost[0])));
    }
    
    //把低级客户端也注入,但是基本不用
    @Bean
    public RestClient restClient(){
        List<HttpHost> httpHostList = new ArrayList<>(hostlist.size());
        //封装es服务端地址
        for(String host:hostlist){
            HttpHost httpHost = new HttpHost(host.split(":")[0], Integer.parseInt(host.split(":")[1]), "http");
            httpHostList.add(httpHost);
        }
        return RestClient.builder(httpHostList.toArray(new HttpHost[0])).build();
    }
    
}

2、索引管理测试

package com.search.test;

import java.io.FileInputStream;

import org.apache.commons.io.IOUtils;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;


@SpringBootTest
@RunWith(SpringRunner.class)
public class TestIndex {

    @Autowired
    RestHighLevelClient client;
    
    @Autowired
    RestClient restClient;
    
    
    //创建索引库
    @Test
    public void testCreateIndex()throws Exception{
        //创建索引请求对象、并设置索引名称
        CreateIndexRequest createIndexRequest = new CreateIndexRequest("course");
        //设置参数
        Settings settings = Settings.builder().put("number_of_shards", 1)
                          .put("number_of_replicas",0)
                          .build();
        createIndexRequest.settings(settings);
        FileInputStream is = new FileInputStream(this.getClass().getResource("/").getPath()+"mapping.json");
        String mappingJson = IOUtils.toString(is);
        System.err.println(mappingJson);
        //设置映射
        createIndexRequest.mapping("doc",mappingJson,XContentType.JSON);
        //创建索引操作对象
        IndicesClient indices = client.indices();
        CreateIndexResponse createIndexResponse = indices.create(createIndexRequest);
        //获得相应是否成功
        boolean acknowledged = createIndexResponse.isAcknowledged();
        System.out.println(acknowledged);
    }
    
    //删除索引库
    @Test
    public void testDeleteIndex()throws Exception{
        //穿建删除索引库请求对象
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("course");
        //删除索引库
        DeleteIndexResponse deleteIndexResponse= client.indices().delete(deleteIndexRequest);        
        //删除结果
        boolean acknowledged = deleteIndexResponse.isAcknowledged();
        System.out.println(acknowledged);
    }
}

mapping.json

         {
                "properties": {
                    "description": {
                        "type": "text",
                        "analyzer": "ik_max_word",
                        "search_analyzer": "ik_smart"
                    },
                    "name": {
                        "type": "text",
                        "analyzer": "ik_max_word",
                        "search_analyzer": "ik_smart"
                    },
                    "pic":{
                        "type":"text",
                        "index":false
                    },
                    "price": {
                        "type": "float"
                    },
                    "studymodel": {
                        "type": "keyword"
                    },
                    "timestamp": {
                        "type": "date",
                        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
                    }
                }
            }

这里特别注意: 使用了比例因子浮点数 ,索引库创建成功之后,在head客户端,数据浏览的字段结构中没有展示,但是实际数据中是存在的,已经成功了

3、文档管理测试

package com.xuecheng.search.test;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.IOUtils;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class TestDocument {

    @Autowired
    private RestHighLevelClient client;
    
    //添加文档
    @Test
    public void testAddDoc() throws Exception{
        
        //加载准备好了的json数据
        InputStream is = new FileInputStream(this.getClass().getResource("/").getPath()+"document.json");
        String docJsonStr = IOUtils.toString(is);
        System.err.println(docJsonStr);
        //获取索引库对象
        IndexRequest indexRequest = new IndexRequest("course","doc"); //特别注意doc不要掉、否则报错org.elasticsearch.action.ActionRequestValidationException: Validation Failed: 1: type is missing;
        indexRequest.source(docJsonStr, XContentType.JSON);
        //往索引库添加文档,这个动作也叫索引
        IndexResponse indexResponse = client.index(indexRequest);
        //打印结果
        System.out.println(indexResponse.getResult());
    }
    
    /**
     * 查询文档(根据id查)
     * 结果
     * {
     *   "description":"Bootstrap是由Twitter推出的一个前台页面开发框架,在行业之中使用较为广泛。
     *                 此开发框架包 含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)
     *                 轻松的实现一个不受浏览器限制的 精美界面效果。",
     *   "name":"Bootstrap开发框架",
     *   "studymodel":"201001",
     *   "price":62.658
     * }
     */
    
    @Test
    public void testGetDoc()throws Exception{
        
        GetRequest getRequest = new GetRequest("course",
                                               "doc",
                                               "TOFP1mcBf3IfcTiHcsXB");
        GetResponse getResponse = client.get(getRequest);
        if(getResponse.isExists()){
            String sourceAsString = getResponse.getSourceAsString();
            System.out.println(sourceAsString);
        }
    }
    
    /**
     * 更新文档
     * 打印结果: OK
     * 注意这里采用的是局部更新:只修改map中设置的字段,没有的不会更新。
     * 更新文档的实际顺序是: 检索文档、标记删除、创建新文档、删除原文档
     * 创建新文档就会重构索引(分词-重构倒排索引树)
     * 
     */
    @Test
    public void testUpdateDoc()throws Exception{
        UpdateRequest updateRequest = new UpdateRequest("course",
                          "doc",
                          "TOFP1mcBf3IfcTiHcsXB");
        Map<String, String> map = new HashMap<String,String>();
        map.put("name", "Bootstrap框架");
        updateRequest.doc(map);
        UpdateResponse updateResponse = client.update(updateRequest);
        System.out.println(updateResponse.status());
    }
    
    /**
     * 删除文档
     * 打印结果:DELETED
     */
    @Test
    public void testDelDoc() throws Exception{
        
        DeleteRequest deleteRequest = new DeleteRequest("course",
                                                        "doc",
                                                        "TOFP1mcBf3IfcTiHcsXB");
        DeleteResponse deleteResponse = client.delete(deleteRequest);
        System.out.println(deleteResponse.getResult());
    }

}

4、搜索管理测试

准备数据

初始化文档:
{
"name": "Bootstrap开发",
"description": "Bootstrap是由Twitter推出的一个前台页面开发框架,是一个非常流行的开发框架,此框架集成了多种页面效果。此开发框架包含了大量的CSS、JS程序代码,可以帮助开发者(尤其是不擅长页面开发的程序人员)轻松的实现一个不受浏览器限制的精美界面效果。",
"studymodel": "201002",
"price":38.6,
"timestamp":"2018-04-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

{
"name": "java编程基础",
"description": "java语言是世界第一编程语言,在软件开发领域使用人数最多。",
"studymodel": "201001",
"price":68.6,
"timestamp":"2018-03-25 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

{
"name": "spring开发基础",
"description": "spring 在java领域非常流行,java程序员都在用。",
"studymodel": "201001",
"price":88.6,
"timestamp":"2018-02-24 19:11:35",
"pic":"group1/M00/00/00/wKhlQFs6RCeAY0pHAAJx5ZjNDEM428.jpg"
}

测试

package com.xuecheng.search.test;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder.Field;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@SpringBootTest
@RunWith(SpringRunner.class)
public class TeseSearch {

    @Autowired
    RestHighLevelClient client;
    
    @Autowired
    RestClient restClient;
    
    
    /**
     * 查询type下所有文档
     * 打印结果:
     *  {"studymodel":"201002","name":"Bootstrap开发"}
        {"studymodel":"201001","name":"java编程基础"}
        {"studymodel":"201001","name":"spring开发基础"}
    
       对应http请求json
       {
         "query": {
           "match_all": {}
         },
         "_source": ["name","studymodel"]
       }
           
     */
    @Test
    public void testSearchAll()throws Exception{
        
        
        //1、构造sourceBuild(source源)
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{})
                           .query(QueryBuilders.matchAllQuery());
        //2、构造查询请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc")
                     .source(searchSourceBuilder);
        //3、client 执行查询
        SearchResponse searchResponse = client.search(searchRequest);
        
        //4、打印结果
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    
    /**
     * 分页查询type下所有文档
     * 
     * json 参数
     * {
     *   "from":0,
     *   "size":1,
     *   "query": {
     *      "match_all": {}
     *   },
     *   "_source": ["name","studymodel"]
     * }
     * 
     * 打印结果
     * {"studymodel":"201002","name":"Bootstrap开发"}
       {"studymodel":"201001","name":"java编程基础"}
     */
    @Test
    public void testSearchAllByPage()throws Exception{
        
        //1、构造sourceBuild
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel"}, new String[]{})
                           .query(QueryBuilders.matchAllQuery())
                           .from(0).size(2);//分页查询,下表从0开始
        
        //2、构造searchRequest请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc")
                     .source(searchSourceBuilder);
        //3、client执行请求
        SearchResponse searchResponse = client.search(searchRequest);
        
        //4、打印结果
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    /**
     * term query: 精确查询、在搜索是会精确匹配关键字、搜索关键字不分词
     * 
     * json 参数
     * {
     *   
     *   "query": {
     *      "term": {
     *          name: "spring"
     *      }
     *   },
     *   "_source": ["name","studymodel"]
     * }
     */
    @Test
    public void testTermQuery()throws Exception{
        
        //1、设置queryBuilder
        TermQueryBuilder termQueryBuild = QueryBuilders.termQuery("name","spring");
        
        //2、设置sourceBuilder
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(termQueryBuild)//设置Term query查询
                           .fetchSource(new String[]{"name","studymodel"}, new String[]{});
        
        //3、构造searchRequest
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc")
                     .source(searchSourceBuilder);
        //4、client发出请求
        SearchResponse searchResponse = client.search(searchRequest);
        
        //5、打印结果
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    
    /**
     * 根据id精确查询:根据提供的多个id去匹配
     * 
     * json 参数
     * {
     *   query{
             "ids": {
                "type": "doc",
                "values": ["TeH_2WcBH5cUK","TuEB2mcBf3IfcTiHccWJ"]
             }
     *   },
     *   "_source": ["name","studymodel"]
     * }
     */
    @Test
    public void testIdsQuery()throws Exception{
        
        //1、够着queryBuild
        //构造idList,注意数组每个元素必须是一个完整的id能匹配的上,第一条没有记录匹配上,第二条中
        String[] idList = new String[]{"TeH_2WcBH5cUK","TuEB2mcBf3IfcTiHccWJ"};
        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("_id",idList);//特别注意用termsQuery,不要用termQuery
        
        //2、构造sourceBuilder
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(termsQueryBuilder)
                           .fetchSource(new String[]{"name","studymodel"}, new String[]{});;
        
        //3、构造searchRequest
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc")
                     .source(searchSourceBuilder);
        //4、client执行
        SearchResponse searchResponse = client.search(searchRequest);
        SearchHits hits = searchResponse.getHits();
        
        //5、打印结果
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    
    /**
     * match Query就是全文检索,收缩方式就是先将搜索字符串分词、然后到索引分词列表去匹配
     * json 参数
     * {
     *   query{
     *     "match": {
     *         "descrition":{  //还是需要指定字段的,description是字段名
     *                 "query": "世界第一",
     *              "operate": "or"  //or表示分词之后,只要有一个匹配即可,and表示分词在文档中都匹配才行
     *         }
     *      },
     *      "_source": ["name","studymodel"]
     *   }
     * }
     */
    @Test
    public void testmatchQuery()throws Exception{
        
        //queryBuild
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("description", "世界第一");
        
        //searchSorcebuilder
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(matchQueryBuilder)
                           .fetchSource(new String[]{"name","studymodel"}, new String[]{});
        
        
        //searchRequest
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc")
                     .source(searchSourceBuilder);
        //client->search
        SearchResponse searchResponse = client.search(searchRequest);
        SearchHits hits = searchResponse.getHits();
        //print end
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    /**
     * minimum_should_match:
     *   or只能表示只要匹配一个即可、minimum_should_match可以指定文档匹配词的占比,注意这个占比的基数是搜索字符串分词的个数
     * json 参数
     * {
     *   query{
     *     "match": {
     *         "descrition":{  //还是需要指定字段的,description是字段名
     *                 "query": "spring开发",
     *              "minimun_should_match": "80%"
     *         }
     *      },
     *      "_source": ["name","studymodel"]
     *   }
     * }
     */
    @Test
    public void testMinimumShouldMatchQuery()throws Exception{
        
        //queryBuild
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("description", "世界第一")
                     .minimumShouldMatch("80%");
        
        
        //searchSourceBuilder
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(matchQueryBuilder)
                           .fetchSource(new String[]{"name","studymodel"}, new String[]{});
        
        //searchRequest
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc")
                     .source(searchSourceBuilder);
        
        SearchResponse searchResponse = client.search(searchRequest);
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    /**
     * multi_match Query:
     *   用于一次匹配多个File进行全文检索、前面match都是一个Field
     *   多个字段可以通过提升boost(权重),来提高得分,实现排序靠前
     *   
     * json 参数
     * {
     *   query{
     *     "multi_match": {
     *         "query": "spring css", //搜索字符串
     *         "minimum_should_match": "50%",
     *         "fields": ["name^10","description"] //设置匹配name 和 description字段,将boost的boost提10倍
     *      }
     *   }
     * }
     */
    @Test
    public void testMultiMatchQuery()throws Exception{
        
        
        //queryBuilder
        MultiMatchQueryBuilder matchQueryBuilder = QueryBuilders.multiMatchQuery("Spring框架","name","description")
                                                                .minimumShouldMatch("50%")//设置百分比
                                                                .field("name", 10);//提升boost
        //searchSourceBuild
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(matchQueryBuilder); 
        
        //searchRequest
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc")
                     .source(searchSourceBuilder);
        //search
        SearchResponse searchResponse = client.search(searchRequest);
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    /**
     * 布尔查询
     *   对应lucene的Boolean查询、实现将多个查询条件结合起来
     *   三个参数:
     *      must:只有符合所有查询的文档才被查询出来,相当于AND
     *      should:至少符合其中一个,相当于OR
     *      must_not:不能符合任意查询条件,相当于NOT
     *      
     * json 参数
     * {
     *   "_source": ["name","pic"],
     *   "from": 0,
     *   "size": 1,
     *   query{
     *     bool:{
     *      must: [
     *         {
     *           "multi_match": {
     *             "query": "spring框架",
     *             "minimum_should_match": "50%",
     *             "fields": ["name^10","description"]
     *           }
     *         },{
     *           "term": {
     *             "studymodel": "201001"
     *           }
     *         }
     *      ]
     *    }  
     *   }
     * }
     */
    @Test
    public void testBooleanQuery()throws Exception{
        
        //1、够着QueryBuild
        
        //构造multiQureyBuilder
        MultiMatchQueryBuilder multiQueryBuilder = QueryBuilders.multiMatchQuery("Spring框架","name","description")
                                                                .minimumShouldMatch("50%")//设置百分比
                                                                .field("name", 10);
         //构造termQueryBuilder
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");
        
        //构造booleanQueryBuilder
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                     .must(multiQueryBuilder)
                     .must(termQueryBuilder);
        
        //2、构造查询源
        SearchSourceBuilder ssb = new SearchSourceBuilder();
        ssb.fetchSource(new String[]{"name","pic"}, new String[]{});
        ssb.query(boolQueryBuilder);
        
        //3、构造请求对象查询
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc");
        searchRequest.source(ssb);
        
        //4、client执行查询
        SearchResponse searchResponse = client.search(searchRequest);
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    
    /**
     * 过滤器:
     *   过滤器判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过滤器性能比查询高、方便缓存
     *   推荐尽量使用过滤器、或则过滤器搭配查询使用
     *   过滤器使用的前提是bool查询
     *   过滤器可以单独使用,但是不能提点multi Query, 因为过滤器每个Query都是单字段过滤
     *      
     * json 参数
     * {
     *   "_source": ["name","pic"],
     *   "from": 0,
     *   "size": 1,
     *   query{
     *     bool:{
     *      must: [
     *         {
     *           "multi_match": {
     *             "query": "spring框架",
     *             "minimum_should_match": "50%",
     *             "fields": ["name^10","description"]
     *           }
     *         }
     *      ],
     *      fileter: [
     *         {
     *            term: {"studymodel": "21001"} //针对字段进行过滤
     *         },{
     *            range: {  //针对范围进行过滤
     *              "price": {"gte":60,"lte":100}
     *            }
     *         }
     *      ]
     *    }  
     *   }
     * }
     */
    @Test
    public void testFileter()throws Exception{
        
        //1、构造QueryBuild
        
        //构造multiQureyBuilder
        MultiMatchQueryBuilder multiQueryBuilder = QueryBuilders.multiMatchQuery("Spring框架","name","description")
                                                                .minimumShouldMatch("50%")//设置百分比
                                                                .field("name", 10);
        
        //构造booleanQueryBuilder
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                     .must(multiQueryBuilder);
        
        //过滤
        boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001"))
                        .filter(QueryBuilders.rangeQuery("price").gte(60).lte(100));
        
        //2、构造查询源
        SearchSourceBuilder ssb = new SearchSourceBuilder();
        ssb.fetchSource(new String[]{"name","pic"}, new String[]{});
        ssb.query(boolQueryBuilder);
        
        //3、构造请求对象查询
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc");
        searchRequest.source(ssb);
        
        //4、client执行查询
        SearchResponse searchResponse = client.search(searchRequest);
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    
    /**
     * 排序:
     * 可以设置排序字段对查询结果进行排序
     * keyword 、date 、float 等可以加
     * 注意text 不能加
     *      
     * json 参数
     * {
     *   "_source": ["name","pic","description","price],
     *   query{
     *     bool:{
     *      fileter: [ //过滤器也可以单独使用,但是只能用于单个字段
     *         {
     *            term: {"studymodel": "21001"} //针对字段进行过滤
     *         },{
     *            range: {  //针对范围进行过滤
     *              "price": {"gte":60,"lte":100}
     *            }
     *         }
     *      ]
     *    }  
     *   },
     *   "sort": [
     *     {
     *       "studymodel": "desc"
     *     },{
     *       "price": "asc"
     *     }
     *   ]
     * }
     */
    @Test
    public void testSort()throws Exception{
        
        //1、构造QueryBuild
        
        //构造booleanQueryBuilder
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        
        //过滤
        boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001"))
                        .filter(QueryBuilders.rangeQuery("price").gte(60).lte(100));
        
        //2、构造查询源
        SearchSourceBuilder ssb = new SearchSourceBuilder();
        ssb.fetchSource(new String[]{"name","pic","studymodel","price"}, new String[]{});
        ssb.query(boolQueryBuilder);
        ssb.sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC));
        ssb.sort(new FieldSortBuilder("price").order(SortOrder.ASC));
        
        //3、构造请求对象查询
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc");
        searchRequest.source(ssb);
        
        //4、client执行查询
        SearchResponse searchResponse = client.search(searchRequest);
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getSourceAsString());
        }
    }
    
    
    /**
     * 高亮显示:
     * 将搜索结果中的一个或多个字突出显示,以便向用户展示匹配的关键字的位置
     *      
     * json 参数
     */
    @Test
    public void testHighlight()throws Exception{
        
        //1、构造QueryBuild
        
        MultiMatchQueryBuilder multiQueryBuilder = QueryBuilders.multiMatchQuery("开发框架", "name","description")
                     .field("name", 10)
                     .minimumShouldMatch("50%");
        
        //构造booleanQueryBuilder
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                                                         .must(multiQueryBuilder);
        
        //过滤
        boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel", "201001"))
                        .filter(QueryBuilders.rangeQuery("price").gte(60).lte(100));
        
        //2、设置高亮
        //设置标签        
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<tag>")//设置签缀
                        .postTags("</tag>");//设置后缀
        //设置高亮字段
        highlightBuilder.fields().add(new Field("name"));
        highlightBuilder.fields().add(new Field("description"));
        
        
        //3、构造查询源
          SearchSourceBuilder ssb = new SearchSourceBuilder();
          ssb.fetchSource(new String[]{"name","pic","studymodel","price"}, new String[]{})
             .query(boolQueryBuilder)
             .sort(new FieldSortBuilder("studymodel").order(SortOrder.DESC))
             .sort(new FieldSortBuilder("price").order(SortOrder.ASC))
           .highlighter(highlightBuilder);
          
        //4、构造请求对象查询
        SearchRequest searchRequest = new SearchRequest("xc_course");
        searchRequest.types("doc")
                     .source(ssb);
        
        //5、client执行查询
        SearchResponse searchResponse = client.search(searchRequest);
        //6、取出高亮字段
        SearchHits hits = searchResponse.getHits();
        for(SearchHit hit:hits){
            System.out.println(hit.getHighlightFields());
        }
    }
    
    
    
    
    
}