ES中的DSL搜索

DSL搜索

DSL(Domain Specific Language)是ES提出的基于json的搜索方式,在搜索时传入特定的json格式的数据来完成不同的搜索需求,DSL比URI搜索方式功能强大,在项目中建议使用DSL方式来完成搜索。

语法:
	GET /index_name/type_name/_search
​	{
​		"commond":{
​			"parameter_name" : "parameter_value"
​		}
​	}
match_all查询

api

GET /java01/course/_search
{
  "query" : { 
    "match_all" : {}
  }
}

搭建工程
pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
    </parent>

    <groupId>com.bjpowernode</groupId>
    <artifactId>springboot_elasticsearch</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <!-- 修改elasticsearch的版本 -->
        <elasticsearch.version>6.2.3</elasticsearch.version>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>elasticsearch-rest-high-level-client</artifactId>
            <version>${elasticsearch.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
    
</project>

application.yml

spring:
  elasticsearch:
    rest:
      uris:
        - http://192.168.226.206:9200 #elasticsearch地址

App启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ElasticsearchApp {
    public static void main(String[] args) {
        SpringApplication.run(ElasticsearchApp.class, args);
    }
}

java client


import com.bjpowernode.ElasticsearchApp;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.After;
import org.junit.Before;
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.SpringJUnit4ClassRunner;

import java.io.IOException;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = ElasticsearchApp.class)
public class IndexReaderTestA {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    private SearchRequest searchRequest;
    private SearchResponse searchResponse;

    @Before
    public void init(){
        //创建search请求对象
        searchRequest = new SearchRequest();
        searchRequest.indices("java01");
        searchRequest.types("course");
    }

    @Test
    public void testMatchAll() throws IOException {
        //创建 参数构造器
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //设置请求参数
        searchRequest.source(searchSourceBuilder);
        //调用search方法
        searchResponse = restHighLevelClient.search(searchRequest);
    }

    @After
    public void show(){
        //遍历查询结果
        SearchHits searchHits = searchResponse.getHits();
        long totalHits = searchHits.getTotalHits();
        System.out.println("共搜索到"+totalHits+"条文档");
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
        }
    }
}
分页查询

api

GET /java01/course/_search
{
  "query": {
    "match_all": {}
  },
  "from": 1,
  "size": 3,
  "sort": [
    {
      "price": "asc"
    }
  ]
}

java client

    //分页查询
    @Test
    public void testPage() throws IOException {
        //查询条件构造器
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        searchSourceBuilder.from(1);
        searchSourceBuilder.size(20);
        searchSourceBuilder.sort("price", SortOrder.DESC);

        searchResponse = restHighLevelClient.search(searchRequest);
    }
match查询

match Query即全文检索,它的搜索方式是先将搜索字符串分词,再使用各各词条从索引中搜索。
api
query:搜索的关键字
operator:or 表示 只要有一个词在文档中出现则就符合条件,and表示每个词都在文档中出现则才符合条件。

GET /java01/course/_search
{
  "query": {
    "match": {
      "name": {
        "query": "spring开发"
      }
    }
  }
}

operator

GET /java01/course/_search
{
  "query": {
    "match": {
      "name": {
        "query": "spring开发",
        "operator":"and"
      }
    }
  }
}

上边的搜索的执行过程是:
1、将“spring开发”分词,分为spring、开发两个词
2、再使用spring和开发两个词去匹配索引中搜索。
3、由于设置了operator为and,必须匹配两个词成功时才返回该文档。
java client

    @Test
    public void testMarchQuery() throws IOException {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("name","spring开发")
                .operator(Operator.AND));
        //设置所搜源
        searchRequest.source(searchSourceBuilder);
        //执行
        searchResponse = restHighLevelClient.search(searchRequest);
    }
multi_match查询

matchQuery是在一个field中去匹配,multiQuery是拿关键字去多个Field中匹配。
api
关键字 “开发”去匹配name 和description字段

GET /java01/course/_search
{
  "query": {
    "multi_match": {
      "query": "开发",
      "fields": ["name","description"]
    }
  }
}

此搜索操作适合构建复杂查询条件,生产环境常用。

java client

    @Test
    public void testMultiMatchQuery() throws IOException {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.multiMatchQuery("开发", "name", "description"));
        //设置搜索源
        searchRequest.source(searchSourceBuilder);
        //执行
        searchResponse = restHighLevelClient.search(searchRequest);
    }

bool查询
布尔查询对应于Lucene的BooleanQuery查询,实现将多个查询组合起来。
参数:
must:表示必须,多个查询条件必须都满足。(通常使用must)
should:表示或者,多个查询条件只要有一个满足即可。
must_not:表示非。
api
查询name包括“开发”并且价格区间是1-100的文档

GET /java01/course/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "开发"
          }
        },
        {
          "range": {
            "price": {
              "gte": 50,
              "lte": 100
            }
          }
        }
      ]
    }
  }
}

java client

    @Test
    public void testBooleanMarch() throws IOException {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //json条件
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("name","开发"));
        boolQueryBuilder.must(QueryBuilders.rangeQuery("price").gte("50").lte(100));
        searchSourceBuilder.query(boolQueryBuilder);

        searchRequest.source(searchSourceBuilder);
        searchResponse = restHighLevelClient.search(searchRequest);
    }
filter查询

过滤查询。此操作实际上就是 query DSL 的补充语法。过滤的时候,不进行任何的匹配分数计算,相对于 query 来说,filter 相对效率较高。Query 要计算搜索匹配相关度分数。Query更加适合复杂的条件搜索。

api

使用bool查询,搜索 name中包含 "开发"的数据,且price在 10~100 之间
不使用 filter, name和price需要计算相关度分数:

GET /java01/course/_search
{
  "query": {
     "bool" : {
        "must":[
            {
               "match": {
                 "name": "开发"
               }
            },
            {
              "range": { # 范围,字段的数据必须满足某范围才有结果。
                "price": {
                  "gte": 10, # 比较符号 lt gt lte gte
                  "lte": 100
                }
              }
            }
        ]
     }
  }
}

使用 filter, price不需要计算相关度分数:

GET /java01/course/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "开发"
          }
        }
      ],
      "filter": {   # 过滤,在已有的搜索结果中进行过滤,满足条件的返回。
        "range": {
          "price": {
            "gte": 1,
            "lte": 100
          }
        }
      }
    }
  }
}

java client

    @Test
    public void testFilterQuery() throws IOException {
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchQuery("name", "开发"));
        boolQueryBuilder.filter(QueryBuilders.rangeQuery("price").gte(10).lte(100));
        searchSourceBuilder.query(boolQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        searchResponse = restHighLevelClient.search(searchRequest);
    }
highlight查询

高亮显示:高亮不是搜索条件,是显示逻辑,在搜索的时候,经常需要对搜索关键字实现高亮显示。

api

GET /java01/course/_search
{
  "query": {
    "match": {
      "name": "开发"
    }
  },
  "highlight": {
      "pre_tags": ["<font color='red'>"],
      "post_tags": ["</font>"],
      "fields": {"name": {}}
  }
}

java client

    @Test
    public void testHighLightQuery() throws IOException {
        //查询条件构造器
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("name", "spring"));
        //设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        highlightBuilder.fields().add(new HighlightBuilder.Field("name"));
        searchSourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(searchSourceBuilder);
        searchResponse = restHighLevelClient.search(searchRequest);
    }


    @After
    public void show() {
        //遍历查询结果
        SearchHits searchHits = searchResponse.getHits();
        long totalHits = searchHits.getTotalHits();
        System.out.println("共搜索到" + totalHits + "条文档");
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            System.out.println(hit.getSourceAsString());
            Map<String, HighlightField> map = hit.getHighlightFields();
            if (map != null && map.size() > 0){
                HighlightField name = map.get("name");
                System.out.println(name.getFragments()[0].toString());
            }
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值