DSL(Domain Specific Language)搜索

DSL(Domain SpecificLanguage)是ES提出的基于json的搜索方式,在搜索时传入特定的json格式的数据来完成不同的搜索需求。

DSL比URI搜索方式功能强大,建议使用DSL方式来完成搜索。

1.查询所有文档

1.1 postman中测试

post http://localhost:9200/wang-003/_search


  "query": {
      "match_all": {}
  }
}

在这里插入图片描述

结果说明:

took:本次操作花费的时间,单位为毫秒。

timed_out:请求是否超时

_shards:说明本次操作共搜索了哪些分片

hits:搜索命中的记录

hits.total : 符合条件的文档总数 hits.hits :匹配度较高的前N个文档

hits.max_score:文档匹配得分,这里为最高分

_score:每个文档都有一个匹配度得分,按照降序排列。

_source:显示了文档的原始内容。

1.2 java代码

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


    @Autowired
    RestHighLevelClient highLevelClient;

    @Test
    public void testSearch() throws IOException {
        //声明搜索请求客户端
        SearchRequest searchRequest = new SearchRequest("wang-003");
        //设置请求类型
        searchRequest.types("doc");
        //构建搜索源对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //告诉搜索源对象,执行搜索时按照什么类型

        //MatchAllQuery===>查询全部
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //将搜索源对象设置到搜索请求客户端中
        searchRequest.source(searchSourceBuilder);
        //使用高版本的客户端进行搜索
        SearchResponse search = highLevelClient.search(searchRequest);
        //获取到 返回值,进行解析
        SearchHits hits = search.getHits();
        //从hits对象中获取到hits数组
        SearchHit[] hits1 = hits.getHits();
        //查询出的总条数
        long totalHits = hits.getTotalHits();
        System.out.println("当前查询出的总数为:"+totalHits);
        //循环获取数据
        for(SearchHit hit:hits1){
            String id = hit.getId();
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            System.out.println("当前查询到的id为:"+id+"数据为:"+sourceAsMap);
        }
    }
}

在这里插入图片描述

2.分页查询

2.1 postman中测试

post http://localhost:9200/wang-003/_search

{
    "from":0,"size":2,
  "query": {
      "match_all": {}
  }
}

在这里插入图片描述

2.2 java代码

int page = 2;//页码
int size = 2;//每页显示个数
int from = (page - 1) * size;//起记录下标

//MatchAllQuery===>查询全部
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());

        //设置分页
        //当前页码
        int page = 2;//页码
        int size = 2;//每页显示个数
        int from = (page - 1) * size;//起记录下标
        searchSourceBuilder.from(from);
        searchSourceBuilder.size(size);

        //将搜索源对象设置到搜索请求客户端中
        searchRequest.source(searchSourceBuilder);

在这里插入图片描述

3.Term Query

Term Query为精确查询,在搜索时会整体匹配关键字,不再将关键字分词。

3.1 postman中测试

post http://localhost:9200/wang-003/_search

{
  "query": {
      "term" : {
          "name": "世"
      }
  }
}

在这里插入图片描述

3.2 java代码

//MatchAllQuery===>查询全部
        //searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //termQuery====>精确查询,不会对关键字分词
        searchSourceBuilder.query(QueryBuilders.termQuery("name","世"));


        //设置分页

4.根据ID精确匹配

4.1 postman中测试

{
  "query": {
     "ids" : {
            "type" : "doc",
            "values" : ["3", "4"]
        }
  }
}

在这里插入图片描述

4.2 java代码

 //termQuery====>精确查询,不会对关键字分词
        //searchSourceBuilder.query(QueryBuilders.termQuery("name","世"));
        
        //声明主键数组
        String[] ids = new  String[]{"3","4"};
        //termsQuery ======>根据主键数组进行精确查询
        searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
        
        //设置分页

在这里插入图片描述

5.match Query全文检索

match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。

match query与Term query区别是match query在搜索前先将搜索关键字分词,再拿各各词语去索引中搜索。

5.1 postman中测试

{
	"query": {
    "match" : {
        "desc" : {
            "query" : "三体世界",
            "operator" : "or"
        }
    }
  }
}

query:搜索的关键字,对于英文关键字如果有多个单词则中间要用半角逗号分隔,而对于中文关键字中间可以用逗号分隔也可以不用。

operator:or 表示 只要有一个词在文档中出现则就符合条件,and表示每个词都在文档中出现则才符合条件。

在这里插入图片描述

5.2 java 代码

 //searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
 
        //matchQuery ======>查询全部,根据关键字,会对关键字进行分词查询 Operator.OR ==>只要满足一个分词的关键字就展示。Operator.AND ===>必须全部满足 才返回
        searchSourceBuilder.query(QueryBuilders.matchQuery("desc","三体世界").operator(Operator.OR));

        //设置分页

6.multi Query

6.1 postman中测试

multiQuery,一次可以匹配多个字段。
使用minimum_should_match可以指定文档匹配词的占比
匹配多个字段时可以提升字段的boost(权重)来提高得分

{
   "query": {
    "multi_match" : {
            "query" : "世界",
            "minimum_should_match": "50%",
            "fields": [ "name", "desc" ]
     }
    }
}

在这里插入图片描述

{
   "query": {
    "multi_match" : {
            "query" : "世界",
            "minimum_should_match": "50%",
            "fields": [ "name", "desc^10" ]
     }
    }
}

在这里插入图片描述

6.2 java代码

//searchSourceBuilder.query(QueryBuilders.matchQuery("desc","三体世界").operator(Operator.OR));
        //mulitMatchQuery=====>根据多个字段进行匹配,进行权重的设置
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery("三体","name","desc").field("desc",10));
        //设置分页

7.布尔查询

布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来。
三个参数:

must:文档必须匹配must所包括的查询条件,相当于 “AND”
should:文档应该匹配should所包括的查询条件其中的一个或多个,相当于 “OR”
must_not:文档不能匹配must_not所包括的该查询条件,相当于“NOT”

 //声明主键数组
        String[] ids = new  String[]{"1","2","3","4"};
        //termsQuery ======>根据主键数组进行精确查询
        //searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
        //如果是bool汇总查询,精确查询这样写
        TermsQueryBuilder s = QueryBuilders.termsQuery("_id", ids);

        //matchQuery ======>查询全部,根据关键字,会对关键字进行分词查询 Operator.OR ==>只要满足一个分词的关键字就展示。Operator.AND ===>必须全部满足 才返回
        //searchSourceBuilder.query(QueryBuilders.matchQuery("desc","三体世界").operator(Operator.OR));
        //mulitMatchQuery=====>根据多个字段进行匹配,进行权重的设置
//        searchSourceBuilder.query(QueryBuilders.multiMatchQuery("三体","name","desc").field("desc",10));
        //如果是bool汇总查询,mulitMatchQuery这样写
        MultiMatchQueryBuilder field = QueryBuilders.multiMatchQuery("三体世界", "name", "desc").field("desc", 10);

        //boolQuery=====>将上边的几个查询条件汇总到一起进行查询
        //精确查找和多和字段匹配查找 TermQueryBuilder和MultiMatchQueryBuilder
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(s);
        boolQueryBuilder.must(field);
        // //将boolquery设置到搜索源对象中
        searchSourceBuilder.query(boolQueryBuilder);

        //设置分页

在这里插入图片描述

8.过滤器

range:范围过虑,保留大于等于60 并且小于等于100的记录。

term:项匹配过虑,保留studymodel等于"201001"的记录。

注意:range和term一次只能对一个Field设置范围过虑。

//boolQuery=====>将上边的几个查询条件汇总到一起进行查询
        //精确查找和多和字段匹配查找 TermQueryBuilder和MultiMatchQueryBuilder
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(s);
        boolQueryBuilder.must(field);

        //rangeQuery 进行范围的过滤,过滤价格 .rangeQuery
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte("10").lte("50"));
        
        // //将boolquery设置到搜索源对象中
        searchSourceBuilder.query(boolQueryBuilder);

在这里插入图片描述

9.排序

可以在字段上添加一个或多个排序,支持在keyword、date、float等类型上添加,text类型的字段上不允许添加排序。

/ //将boolquery设置到搜索源对象中
        searchSourceBuilder.query(boolQueryBuilder);

        //设置排序
        searchSourceBuilder.sort("id", SortOrder.DESC);

        //设置分页

在这里插入图片描述

10 高亮显示

高亮显示可以将搜索结果一个或多个字突出显示,以便向用户展示匹配关键字的位置。

//设置排序
        searchSourceBuilder.sort("id", SortOrder.DESC);

        //设置高亮展示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //设置前缀
        highlightBuilder.preTags("<font style='color:red'>");
        //设置后缀
        highlightBuilder.postTags("</font>");
        //设置高亮展示在那个字段上
        highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
        highlightBuilder.fields().add(new HighlightBuilder.Field("desc"));
        //将高亮设置到搜索对象中
        searchSourceBuilder.highlighter(highlightBuilder);


        //设置分页
        //当前页码
        int page = 1;//页码
        int size = 5;//每页显示个数
        int from = (page - 1) * size;//起记录下标
        searchSourceBuilder.from(from);
        searchSourceBuilder.size(size);

        //将搜索源对象设置到搜索请求客户端中
        searchRequest.source(searchSourceBuilder);
        //使用高版本的客户端进行搜索
        SearchResponse search = highLevelClient.search(searchRequest);
        //获取到 返回值,进行解析
        SearchHits hits = search.getHits();
        //从hits对象中获取到hits数组
        SearchHit[] hits1 = hits.getHits();
        //查询出的总条数
        long totalHits = hits.getTotalHits();
        System.out.println("当前查询出的总数为:"+totalHits);
        //循环获取数据
        for(SearchHit hit:hits1){
            String id = hit.getId();
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            //从hit中获取高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            String name="";
            if(highlightBuilder!=null){
                HighlightField highlightName = highlightFields.get("name");
                if(highlightName!=null){
                    Text[] fragments = highlightName.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for(Text text:fragments){
                        stringBuffer.append(text);
                    }
                    name=stringBuffer.toString();
                }
            }


            System.out.println("当前 高亮的字段为 name========="+name);
            System.out.println("当前查询到的id为:"+id+"数据为:"+sourceAsMap);

在这里插入图片描述
多个字段高亮

 //从hit中获取高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            String name="";
            String desc="";
            if(highlightBuilder!=null){
                HighlightField highlightName = highlightFields.get("name");
                HighlightField highlightDesc = highlightFields.get("desc");
                if(highlightName!=null){
                    Text[] fragments = highlightName.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for(Text text:fragments){
                        stringBuffer.append(text);
                    }
                    name=stringBuffer.toString();
                }
                if(highlightDesc!=null){
                    Text[] fragments = highlightDesc.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for(Text text:fragments){
                        stringBuffer.append(text);
                    }
                    desc=stringBuffer.toString();
                }
            }


            System.out.println("当前 高亮的字段为 name========="+name);
            System.out.println("当前 高亮的字段为 desc========="+desc);
            System.out.println("当前查询到的id为:"+id+"数据为:"+sourceAsMap);

在这里插入图片描述

11.完整代码

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


    @Autowired
    RestHighLevelClient highLevelClient;

    @Test
    public void testSearch() throws IOException {
        //声明搜索请求客户端
        SearchRequest searchRequest = new SearchRequest("wang-003");
        //设置请求类型
        searchRequest.types("doc");
        //构建搜索源对象
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //告诉搜索源对象,执行搜索时按照什么类型

        //MatchAllQuery===>查询全部
        //searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //termQuery====>精确查询,不会对关键字分词
        //searchSourceBuilder.query(QueryBuilders.termQuery("name","世"));
        //声明主键数组
        String[] ids = new  String[]{"1","2","3","4"};
        //termsQuery ======>根据主键数组进行精确查询
        //searchSourceBuilder.query(QueryBuilders.termsQuery("_id",ids));
        //如果是bool汇总查询,精确查询这样写
        TermsQueryBuilder s = QueryBuilders.termsQuery("_id", ids);

        //matchQuery ======>查询全部,根据关键字,会对关键字进行分词查询 Operator.OR ==>只要满足一个分词的关键字就展示。Operator.AND ===>必须全部满足 才返回
        //searchSourceBuilder.query(QueryBuilders.matchQuery("desc","三体世界").operator(Operator.OR));
        //mulitMatchQuery=====>根据多个字段进行匹配,进行权重的设置
//        searchSourceBuilder.query(QueryBuilders.multiMatchQuery("三体","name","desc").field("desc",10));
        //如果是bool汇总查询,mulitMatchQuery这样写
        MultiMatchQueryBuilder field = QueryBuilders.multiMatchQuery("三体世界", "name", "desc").field("desc", 10);

        //boolQuery=====>将上边的几个查询条件汇总到一起进行查询
        //精确查找和多和字段匹配查找 TermQueryBuilder和MultiMatchQueryBuilder
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(s);
        boolQueryBuilder.must(field);
        //rangeQuery 进行范围的过滤,过滤价格 .rangeQuery
        //boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte("10").lte("500"));
        // //将boolquery设置到搜索源对象中
        searchSourceBuilder.query(boolQueryBuilder);
        //设置排序
        searchSourceBuilder.sort("id", SortOrder.DESC);

        //设置高亮展示
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        //设置前缀
        highlightBuilder.preTags("<font style='color:red'>");
        //设置后缀
        highlightBuilder.postTags("</font>");
        //设置高亮展示在那个字段上
        highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
        highlightBuilder.fields().add(new HighlightBuilder.Field("desc"));
        //将高亮设置到搜索对象中
        searchSourceBuilder.highlighter(highlightBuilder);


        //设置分页
        //当前页码
        int page = 1;//页码
        int size = 5;//每页显示个数
        int from = (page - 1) * size;//起记录下标
        searchSourceBuilder.from(from);
        searchSourceBuilder.size(size);

        //将搜索源对象设置到搜索请求客户端中
        searchRequest.source(searchSourceBuilder);
        //使用高版本的客户端进行搜索
        SearchResponse search = highLevelClient.search(searchRequest);
        //获取到 返回值,进行解析
        SearchHits hits = search.getHits();
        //从hits对象中获取到hits数组
        SearchHit[] hits1 = hits.getHits();
        //查询出的总条数
        long totalHits = hits.getTotalHits();
        System.out.println("当前查询出的总数为:"+totalHits);
        //循环获取数据
        for(SearchHit hit:hits1){
            String id = hit.getId();
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            //从hit中获取高亮字段
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            String name="";
            String desc="";
            if(highlightBuilder!=null){
                HighlightField highlightName = highlightFields.get("name");
                HighlightField highlightDesc = highlightFields.get("desc");
                if(highlightName!=null){
                    Text[] fragments = highlightName.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for(Text text:fragments){
                        stringBuffer.append(text);
                    }
                    name=stringBuffer.toString();
                }
                if(highlightDesc!=null){
                    Text[] fragments = highlightDesc.getFragments();
                    StringBuffer stringBuffer = new StringBuffer();
                    for(Text text:fragments){
                        stringBuffer.append(text);
                    }
                    desc=stringBuffer.toString();
                }
            }


            System.out.println("当前 高亮的字段为 name========="+name);
            System.out.println("当前 高亮的字段为 desc========="+desc);
            System.out.println("当前查询到的id为:"+id+"数据为:"+sourceAsMap);
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值