Java代码实现elasticSearch的DSL复合查询

elasticsearch提供DSL(domain specific language)查询,就是以json格式定义查询条件实现复杂条件查询。

DSL查询分为俩大类: 

  叶子查询:一般是在特定的字段里查询特定值,属于简单查询,很少单独使用。

  复合查询:以逻辑方式组合多个叶子查询后者更改叶子查询的行为方式。

我们还可以对查询结果做进一步的处理,博包括:排序、分页、高亮、聚合等等。

叶子查询:  叶子查询进一步细分有

  全文检索查询:利用分词器对用户输入内容分词,然后去词条列表中匹配。

  精确查询:不对用户输入内容分词,直接精确匹配,一般是查找keyword、数值、日期、布尔类型等等。

  地理查询:用于搜索地理位置。

 代码实现: 我已经把我数据库的信息存储一份到elasticSearch中了,各位在进行下面操作时不忘了把自己数据库的数据存储一份到elasticsearch。  在写代码时,我会先告诉大家在elasticsearch中的代码实现,然后根据elasticsearch的代码去实现Java代码。

    全文检索查询: match(单字段查询)    和    multi_match(多字段查询)        

注意:es中查询数据,最多查询到10000条,但控制台只会显示出10条。所以要注意看到查询结果中显示查询到数据10000条时,很可能符合条件的数据不止10000条。

#match查询所有
GET /items/_search
{
  "query": {
    "match": {
      "name": "脱脂牛奶"
    }
  }
}

控制台返回: 

 我来说一下返回数据中最外层的数据是什么意思:  took 表示查询话费的时间;timed_out表示是否超时;_shared 是分片情况;hits是命中情况,就是符合条件的基本信息。

我们主要看hits命中信息: 其中total中的vaule和relation分别是查询到的信息数量 和 查询方式equals。 max_score 表示最大相关性得分,es有个底层算法可以帮我们算出每条信息与我们搜索内容的相关性。然后后面又是一个hits,这个内层的hits就是我们查询到的每条数据的详细信息,_index表示在哪个索引库中进行的操作;_type表示对什么进行的操作,_source就是查到的每条数据了。

下面我们开始写相应的Java代码:

首先我们要初始化对es操作的客户端:

 private RestHighLevelClient client;

    @BeforeEach
    void setUp() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://localhost:9200")));
    }

    @AfterEach
    void tearDown() throws IOException {
        if (client != null) {
            client.close();
        }
    }

 然后我们就可以用client对es进行各种操作了。

//查询单、多字段
    @Test
    void testMatch() throws IOException {
        SearchRequest request = new SearchRequest("items");//索引库名
        //单字段
        request.source().query(QueryBuilders.matchQuery("name", "脱脂牛奶"));

        //多字段
        //request.source().query(QueryBuilders.multiMatchQuery("脱脂牛奶", "name", "category"));

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //解析数据
        SearchHits searchHits = response.getHits();
        SearchHit[] hits = searchHits.getHits();
        for (SearchHit hit : hits) {
            String source = hit.getSourceAsString();
            ItemDoc itemDoc = JSONUtil.toBean(source, ItemDoc.class);
            System.out.println("itemDoc: " + itemDoc);
        }
    }

首先创建一个用于发送请求的request对象,用于查询的用SearchRequest  ;

单字段就是只对一个字段做查询,比如查询name字段中有 脱脂牛奶 的 ,格式是matchQuery("name", "脱脂牛奶")先写字段名,在写查询内容 。多字段就是对多个字段进行查询,格式是 multiMatchQuery("脱脂牛奶", "name", "category") 先写查询内容,在写n个字段名,就是查询name中有"脱脂牛奶"的或者category中有"脱脂牛奶"的。发送请求用client.search(...) 返回响应数据response。

然后就是解析数据:这个要根据我们在es中做查询时返回的数据格式:我们要的是内层的那个hits中的source中的数据。而我们获取的response是最外面的大括号,里面有 took,timed_out,shards,hits。所以要先获取外层hits:SearchHits searchHits = response.getHits();然后在获取内层hits:SearchHit[] hits = searchHits.getHits();最后获取source:String source = hit.getSourceAsString();这样我们就获得了查询的详细信息了。

精确查询:

//精确查询
    @Test
    void testTerm() throws IOException {
        SearchRequest request = new SearchRequest("items");
        request.source().query(QueryBuilders.termQuery("brand", "德亚"));

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //解析数据
        explainData(response);
    }

    //范围查询
    @Test
    void testRange() throws IOException {
        SearchRequest request = new SearchRequest("items");
        request.source().query(QueryBuilders.rangeQuery("price").gte(10000).lte(15000));
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        explainData(response);
    }

接下来说复合查询:可分为俩类

   第一类:基于逻辑运算组合叶子查询,例如bool;

  第二类:基于某种算法修改查询时的文档相关性算分,从而改变文档排名。

bool查询: 是一个或多个查询子句的组合,组合方式有:

must:必须匹配每个子查询,类似“与”;should:选择性匹配子查询,类似“或”;

must_not:必须不匹配,不参与算法,类似“非” ;filter:必须匹配,不参与算法。

这里说的算法指的是计算该数据与搜索内容相关性的算法,像品牌、价格就不需要参与算法。

@Test
    void testBool() throws IOException {
        SearchRequest request = new SearchRequest("items");

        request.source().query(QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("name", "脱脂牛奶"))
                .filter(QueryBuilders.termQuery("brand", "德亚"))
                .filter(QueryBuilders.rangeQuery("price").lte(30000)));

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        explainData(response);
    }
//我把解析数据的操作写成了一个方法
private void explainData(SearchResponse response) {
        SearchHits searchHits = response.getHits();

        TotalHits totalHits = searchHits.getTotalHits();
        System.out.println("total: " + totalHits);


        SearchHit[] hits = searchHits.getHits();

        for (SearchHit hit : hits) {
            String source = hit.getSourceAsString();

            ItemDoc itemDoc = JSONUtil.toBean(source, ItemDoc.class);

            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if (highlightFields!=null&&!highlightFields.isEmpty()) {
                HighlightField name = highlightFields.get("name");
                if (name!=null){
                    String hm = name.getFragments()[0].toString();
                 itemDoc.setName(hm);
                }

                System.out.println("itemDoc: " + itemDoc);
            }

        }
    }

 

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个Java代码示例,用于执行ElasticSearch中的多值查询: ```java import org.elasticsearch.index.query.QueryBuilders; import org.elasticsearch.index.query.BoolQueryBuilder; import org.elasticsearch.index.query.MatchQueryBuilder; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.indices.GetIndexRequest; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.action.search.SearchRequest; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.search.builder.SearchSourceBuilder; import org.elasticsearch.search.SearchHit; import java.util.Arrays; import java.util.List; public class MultiValueQueryExample { public static void main(String[] args) throws Exception { // 创建ElasticSearch客户端 RestHighLevelClient client = new RestHighLevelClient( RestClient.builder(new HttpHost("localhost", 9200, "http")) ); // 定义查询条件 List<String> values = Arrays.asList("value1", "value2", "value3"); BoolQueryBuilder boolQuery = QueryBuilders.boolQuery(); for (String value : values) { MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("field_name", value); boolQuery.should(matchQuery); } // 构建搜索请求 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); sourceBuilder.query(boolQuery); SearchRequest searchRequest = new SearchRequest("index_name"); searchRequest.source(sourceBuilder); // 执行搜索请求 SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT); // 处理搜索结果 SearchHit[] searchHits = searchResponse.getHits().getHits(); for (SearchHit hit : searchHits) { // 处理每个搜索结果 System.out.println(hit.getSourceAsString()); } // 关闭ElasticSearch客户端 client.close(); } } ``` 在这个示例中,我们首先创建了一个ElasticSearch客户端,然后定义了一个包含多个值的查询条件。我们使用布尔查询(BoolQueryBuilder)来组合这些查询条件,使用should()方法将每个查询条件添加到布尔查询中。 接下来,我们使用SearchSourceBuilder构建搜索请求,并将布尔查询添加到搜索请求中。我们还指定了要搜索的索引名称("index_name")。 最后,我们通过调用RestHighLevelClient.search()方法来执行搜索请求,并处理搜索结果。我们使用SearchHit对象遍历搜索结果,并打印每个结果的源字符串(getSourceAsString()方法)。 请注意,我们使用了try-with-resources语句来自动关闭ElasticSearch客户端。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值