ElasticSearch学习(五),搜索管理

1、准备环境

1)创建 xc_course 索引库。
 
2)创建如下映射
post http://localhost:9200/xc_course/doc/_mapping
 
{
    "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"
        }
    }
}

3)xc_course/doc中插入以下数据:

http://localhost:9200/xc_course/doc/1

{
    "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"
}

http://localhost:9200/xc_course/doc/2

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

http://localhost:9200/xc_course/doc/3

{
    "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"
}

2、简单搜索

简单搜索就是通过url进行查询,以get方式请求ES

格式: get ../_search?q=.....
 
q :搜索字符串
例子:
?q=name:spring 搜索 name 中包括 spring 的文档。
 
3、DSL 搜索
 
DSL(Domain Specifific Language) ES 提出的基于 json 的搜索方式,在搜索时传入特定的 json 格式的数据来完成不
同的搜索需求。
 
DSL URI 搜索方式功能强大,在项目中建议使用 DSL 方式来完成搜索。

 

4、查询所有文档

1)查询所有索引库的文档。

发送:post http://localhost:9200/_search

2)查询指定索引库指定类型下的文档。(通过使用此方法)
 
发送: post http://localhost:9200/xc_course/doc/_search
 
{
    "query":{
        "match_all":{

        }
    },
    "_source":[
        "name",
        "studymodel"
    ]
}
_source source 源过虑设置,指定结果中所包括的字段有哪些。
 
结果说明:
 
took :本次操作花费的时间,单位为毫秒。
 
timed_out :请求是否超时
 
_shards :说明本次操作共搜索了哪些分片
 
hits :搜索命中的记录
 
hits.total : 符合条件的文档总数 hits.hits :匹配度较高的前 N 个文档
 
hits.max_score :文档匹配得分,这里为最高分
 
_score :每个文档都有一个匹配度得分,按照降序排列。
 
_source :显示了文档的原始内容。
 
 
3)Java 操作
 
    //搜索全部记录
    @Test
    public void testSearchAll() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //搜索方式
        //matchAllQuery搜索全部
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

5、分页查询

1)API
    ES 支持分页查询,传入两个参数: from size
    form :表示起始文档的下标,从 0 开始。
    size :查询的文档数量。
    发送: post http://localhost:9200/xc_course/doc/_search
{
    "from":0,
    "size":1,
    "query":{
        "match_all":{

        }
    },
    "_source":[
        "name",
        "studymodel"
    ]
}

2)Java 操作

 //分页查询
    @Test
    public void testSearchPage() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置分页参数
        //页码
        int page = 1;
        //每页记录数
        int size = 1;
        //计算出记录起始下标
        int from  = (page-1)*size;
        searchSourceBuilder.from(from);//起始记录下标,从0开始
        searchSourceBuilder.size(size);//每页显示的记录数
        //搜索方式
        //matchAllQuery搜索全部
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

6、Term Query

1)API:

    Term Query 为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。
     发送: post http://localhost:9200/xc_course/doc/_search
{
    "query":{
        "term":{
            "name":"spring"
        }
    },
    "_source":[
        "name",
        "studymodel"
    ]
}
上边的搜索会查询 name 包括 “spring” 这个词的文档。
 
2)Java 操作
 
//TermQuery
    @Test
    public void testTermQuery() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //设置分页参数
        //页码
        int page = 1;
        //每页记录数
        int size = 1;
        //计算出记录起始下标
        int from  = (page-1)*size;
        searchSourceBuilder.from(from);//起始记录下标,从0开始
        searchSourceBuilder.size(size);//每页显示的记录数
        //搜索方式
        //termQuery
        searchSourceBuilder.query(QueryBuilders.termQuery("name","spring"));
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

 

7、根据id精确匹配

1)API 

    ES 提供根据多个 id 值匹配的方法:
    测试:
    post http://127.0.0.1:9200/xc_course/doc/_search
{
    "query":{
        "ids":{
            "type":"doc",
            "values":[
                "3",
                "4",
                "100"
            ]
        }
    }
}

2)Java 操作

 //根据id查询
    @Test
    public void testTermQueryByIds() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //搜索方式
        //根据id查询
        //定义id
        String[] ids = new String[]{"1","2"};
        searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

8、match Query

1)API:

    match Query 即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。
    match query Term query 区别是 match query 在搜索前先将搜索关键字分词,再拿各各词语去索引中搜索。
    发送: post http://localhost:9200/xc_course/doc/_search
{
    "query":{
        "match":{
            "description":{
                "query":"spring开发",
                "operator":"or"
            }
        }
    }
}
query :搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用
逗号分隔也可以不用。
 
operator or 表示 只要有一个词在文档中出现则就符合条件, and 表示每个词都在文档中出现则才符合条件。
上边的搜索的执行过程是:
1 、将 “spring 开发 分词,分为 spring 、开发两个词
2 、再使用 spring 和开发两个词去匹配索引中搜索。
3 、由于设置了 operator or ,只要有一个词匹配成功则就返回该文档。

2) Java 操作

//MatchQuery
    @Test
    public void testMatchQuery() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //搜索方式
        //MatchQuery
        searchSourceBuilder.query(QueryBuilders.matchQuery("description","spring开发框架")
                .minimumShouldMatch("80%"));
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

3)minimum_should_match

上边使用的 operator = or 表示只要有一个词匹配上就得分,如果实现三个词至少有两个词匹配如何实现?
使用 minimum_should_match 可以指定文档匹配词的占比:
比如搜索语句如下:
 
{
    "query":{
        "match":{
            "description":{
                "query":"spring开发框架",
                "minimum_should_match":"80%"
            }
        }
    }
}
“spring 开发框架 会被分为三个词: spring 、开发、框架
设置 "minimum_should_match": "80%" 表示,三个词在文档的匹配占比为 80% ,即 3*0.8=2.4 ,向上取整得 2 ,表
示至少有两个词在文档中要匹配成功。

 

Java 操作

//匹配关键字 
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("description", "前台页面开发框架 架 构") .minimumShouldMatch("80%");
//设置匹配占比 
searchSourceBuilder.query(matchQueryBuilder);

9、multi Query

1)API:
     上边学习的 termQuery matchQuery 一次只能匹配一个 Field ,本节学习 multiQuery ,一次可以匹配多个字段。
 
      1 、基本使用
           单项匹配是在一个 fifield 中去匹配,多项匹配是拿关键字去多个 Field 中匹配。
           例子:
                 发送: post http://localhost:9200/xc_course/doc/_search
                拿关键字 “spring css” 去匹配 name description 字段。
{
    "query":{
        "multi_match":{
            "query":"spring css",
            "minimum_should_match":"50%",
            "fields":[
                "name",
                "description"
            ]
        }
    }
}
        2 、提升 boost
              匹配多个字段时可以提升字段的 boost (权重)来提高得分
              例子:
                    提升 boost 之前,执行下边的查询:
{
    "query":{
        "multi_match":{
            "query":"spring框架",
            "minimum_should_match":"50%",
            "fields":[
                "name",
                "description"
            ]
        }
    }
}
通过查询发现 Bootstrap 排在前边。
提升 boost ,通常关键字匹配上 name 的权重要比匹配上 description 的权重高,这里可以对 name 的权重提升。
{
    "query":{
        "multi_match":{
            "query":"spring框架",
            "minimum_should_match":"50%",
            "fields":[
                "name^10",
                "description"
            ]
        }
    }
}
“name^10” 表示权重提升 10 倍,执行上边的查询,发现 name 中包括 spring 关键字的文档排在前边。

 

2)Java 操作

//MultiMatchQuery
    @Test
    public void testMultiMatchQuery() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //搜索方式
        //MultiMatchQuery
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery("spring css","name","description")
                .minimumShouldMatch("50%")
                .field("name",10));
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

10、布尔查询

1)API:

     布尔查询对应于 Lucene BooleanQuery 查询,实现将多个查询组合起来。
     三个参数:
           must :文档必须匹配 must 所包括的查询条件,相当于 “AND”
          should :文档应该匹配 should 所包括的查询条件其 中的一个或多个,相当于 "OR"
          must_not :文档不能匹配 must_not 所包括的该查询条件,相当于 “NOT”
 
         分别使用 must should must_not 测试下边的查询:
         发送: POST http://localhost:9200/xc_course/doc/_search
{
    "_source":[
        "name",
        "studymodel",
        "description"
    ],
    "from":0,
    "size":1,
    "query":{
        "bool":{
            "must":[
                {
                    "multi_match":{
                        "query":"spring框架",
                        "minimum_should_match":"50%",
                        "fields":[
                            "name^10",
                            "description"
                        ]
                    }
                },
                {
                    "term":{
                        "studymodel":"201001"
                    }
                }
            ]
        }
    }
}
must :表示必须,多个查询条件必须都满足。(通常使用 must
should :表示或者,多个查询条件只要有一个满足即可。
must_not :表示非。
 
2)Java 操作
 
//BoolQuery
    @Test
    public void testBoolQuery() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //boolQuery搜索方式
        //先定义一个MultiMatchQuery
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring css", "name", "description")
                .minimumShouldMatch("50%")
                .field("name", 10);
        //再定义一个termQuery
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("studymodel", "201001");

        //定义一个boolQuery
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(multiMatchQueryBuilder);
        boolQueryBuilder.must(termQueryBuilder);

        searchSourceBuilder.query(boolQueryBuilder);
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

11、过滤器

1)API:

     过虑是针对搜索的结果进行过虑,过虑器主要判断的是文档是否匹配,不去计算和判断文档的匹配度得分,所以过
虑器性能比查询要高,且方便缓存,推荐尽量使用过虑器去实现查询或者过虑器和查询共同使用。
过虑器在布尔查询中使用,下边是在搜索结果的基础上进行过虑:
 
{
    "_source":[
        "name",
        "studymodel",
        "description",
        "price"
    ],
    "query":{
        "bool":{
            "must":[
                {
                    "multi_match":{
                        "query":"spring框架",
                        "minimum_should_match":"50%",
                        "fields":[
                            "name^10",
                            "description"
                        ]
                    }
                }
            ],
            "filter":[
                {
                    "term":{
                        "studymodel":"201001"
                    }
                },
                {
                    "range":{
                        "price":{
                            "gte":60,
                            "lte":100
                        }
                    }
                }
            ]
        }
    }
}
range :范围过虑,保留大于等于 60 并且小于等于 100 的记录。
term :项匹配过虑,保留 studymodel 等于 "201001" 的记录。
注意: range term 一次只能对一个 Field 设置范围过虑。
 
2)Java 操作
//filter
    @Test
    public void testFilter() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //boolQuery搜索方式
        //先定义一个MultiMatchQuery
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("spring css", "name", "description")
                .minimumShouldMatch("50%")
                .field("name", 10);

        //定义一个boolQuery
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(multiMatchQueryBuilder);
        //定义过虑器
        boolQueryBuilder.filter(QueryBuilders.termQuery("studymodel","201001"));
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(90).lte(100));

        searchSourceBuilder.query(boolQueryBuilder);
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

 

11、排序

1)API:

可以在字段上添加一个或多个排序,支持在 keyword date flfloat 等类型上添加, text 类型的字段上不允许添加排
序。
发送 POST http://localhost:9200/xc_course/doc/_search
过虑 0--10 元价格范围的文档,并且对结果进行排序,先按 studymodel 降序,再按价格升序
{
    "_source":[
        "name",
        "studymodel",
        "description",
        "price"
    ],
    "query":{
        "bool":{
            "filter":[
                {
                    "range":{
                        "price":{
                            "gte":0,
                            "lte":100
                        }
                    }
                }
            ]
        }
    },
    "sort":[
        {
            "studymodel":"desc"
        },
        {
            "price":"asc"
        }
    ]
}

2)Java 操作

//Sort
    @Test
    public void testSort() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //boolQuery搜索方式
        //定义一个boolQuery
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //定义过虑器
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));

        searchSourceBuilder.query(boolQueryBuilder);
        //添加排序
        searchSourceBuilder.sort("studymodel", SortOrder.DESC);
        searchSourceBuilder.sort("price", SortOrder.ASC);
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});
        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            String name = (String) sourceAsMap.get("name");
            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

12、高亮显示

1)API:

     高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。
     在搜索语句中添加 highlight 即可实现,如下:
     Post http://127.0.0.1:9200/xc_course/doc/_search
 
{
    "_source":[
        "name",
        "studymodel",
        "description",
        "price"
    ],
    "query":{
        "bool":{
            "must":[
                {
                    "multi_match":{
                        "query":"开发框架",
                        "minimum_should_match":"50%",
                        "fields":[
                            "name^10",
                            "description"
                        ],
                        "type":"best_fields"
                    }
                }
            ],
            "filter":[
                {
                    "range":{
                        "price":{
                            "gte":0,
                            "lte":100
                        }
                    }
                }
            ]
        }
    },
    "sort":[
        {
            "price":"asc"
        }
    ],
    "highlight":{
        "pre_tags":[
            "<tag1>"
        ],
        "post_tags":[
            "</tag2>"
        ],
        "fields":{
            "name":{

            },
            "description":{

            }
        }
    }
}

2)Java 操作

//Highlight
    @Test
    public void testHighlight() throws IOException, ParseException {
        //搜索请求对象
        SearchRequest searchRequest = new SearchRequest("xc_course");
        //指定类型
        searchRequest.types("doc");
        //搜索源构建对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

        //boolQuery搜索方式
        //先定义一个MultiMatchQuery
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("开发框架", "name", "description")
                .minimumShouldMatch("50%")
                .field("name", 10);

        //定义一个boolQuery
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(multiMatchQueryBuilder);
        //定义过虑器
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(0).lte(100));

        searchSourceBuilder.query(boolQueryBuilder);
        //设置源字段过虑,第一个参数结果集包括哪些字段,第二个参数表示结果集不包括哪些字段
        searchSourceBuilder.fetchSource(new String[]{"name","studymodel","price","timestamp"},new String[]{});

        //设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<tag>");
        highlightBuilder.postTags("</tag>");
        highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
//        highlightBuilder.fields().add(new HighlightBuilder.Field("description"));
        searchSourceBuilder.highlighter(highlightBuilder);

        //向搜索请求对象中设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行搜索,向ES发起http请求
        SearchResponse searchResponse = client.search(searchRequest);
        //搜索结果
        SearchHits hits = searchResponse.getHits();
        //匹配到的总记录数
        long totalHits = hits.getTotalHits();
        //得到匹配度高的文档
        SearchHit[] searchHits = hits.getHits();
        //日期格式化对象
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for(SearchHit hit:searchHits){
            //文档的主键
            String id = hit.getId();
            //源文档内容
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            //源文档的name字段内容
            String name = (String) sourceAsMap.get("name");
            //取出高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if(highlightFields!=null){
                //取出name高亮字段
                HighlightField nameHighlightField = highlightFields.get("name");
                if(nameHighlightField!=null){
                    Text[] fragments = nameHighlightField.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for(Text text:fragments){
                        stringBuffer.append(text);
                    }
                    name = stringBuffer.toString();
                }
            }

            //由于前边设置了源文档字段过虑,这时description是取不到的
            String description = (String) sourceAsMap.get("description");
            //学习模式
            String studymodel = (String) sourceAsMap.get("studymodel");
            //价格
            Double price = (Double) sourceAsMap.get("price");
            //日期
            Date timestamp = dateFormat.parse((String) sourceAsMap.get("timestamp"));
            System.out.println(name);
            System.out.println(studymodel);
            System.out.println(description);
        }

    }

 

 

 

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值