ElasticSearch查询之——Search API

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElasticSearch查询之——Search API相关的知识,希望对你有一定的参考价值。

参考技术A

实现对ES中存储的数据进行查询分析,使用的关键字是 _search ,比如下面的API

小例子:查询job字段中包含java的文档,结果根据age属性进行升序排序,返回第1个文档,如果超过1s没有结束,则以超时结束。

多词匹配之间使用空格进行隔开,词语之间的关系为 “或”

若想使用词语匹配,需要用双引号括起来

泛查询在之前其实就有演示过,即像 q = xiaoming 这种不指定检索字段范围,会在所有字段中进行检索的查询即称为泛查询。反之,如果指定了字段,就能大大缩小范围。常见的指定字段的方式为 字段:检索条件字符 。

SearchURI中也可以使用和和 Query DSL 类型的布尔操作符,不过具体的使用规则略有不同,具体的规则如下:

需要注意的是, “+” 号在url中会被解析为空格,要使用encode后的结果才可以,我们需要用%2B来替代一下。

范围查询支持数据范围和日期范围的查询,具体的表达式写法有两种方式:

Query URI 支持我们使用通配符来进行模糊查询, ? 表示一个字符, * 表示一个或者多个字符

注意: 通配符匹配执行效率低,且占用较多内存 ,数据较多时不建议使用
如无特殊需求,不要将 ?/* 放在最前面(因为会加大匹配的范围,降低匹配效率)

Query URI 支持我们使用正则表达式来进行检索

当我们对于检索条件字符不明确时, Query URI 支持我们使用近似值来作为模糊查询的条件,这个和之前的通配符不太一样,通配符很多时候是基于我们清楚某一段字符中的某个区间内容了(比如说最终的结果是 xiaoming ,我们可以根据知道的字符进行匹配,比如 xiao* 、 *ming )。而近似值匹配可以是众多模糊匹配的并集。

Request Body Search 字如其意,就是通过在 body 中添加请求体来实现搜索。我们在第二节中学习了 Query URI 的众多语法可能会觉得它已经很强大,但实际上第三节的将要介绍的 Query DSL 会更加强大和灵活,不仅支持URI写法的所有语法,还支持更多高阶的语法查询。也是我们日常工作中更为常用的一种检索方式。

字段类的查询可以分为全文匹配和单词匹配,两者的区别在于会不会对查询语句进行分词后处理,全文匹配会(match、match_phrase),单词匹配(term、terms、range)不会。

该方法用于对字段作检索,对字段有顺序要求

Query String Query 其实就相当于 Query URI 的请求体写法

Simple Query String Query 类似于Query String,但是会忽略错误的查询语法,并且仅支持部分查询语法。其常用的逻辑符号如下,不能使用AND、OR、NOT等关键词,而是要对应地使用 + | - 。

Term Query 将查询语句作为整个单词进行查询,即不对查询语句做分词处理

terms query 和 term query 类似,差别在于后者可以同时支持多个全词匹配

Query DSL 支持我们使用 Range Query 来使用范围匹配

拓展:

我们可以发现,之前列举的字段类查询只能够满足单个字段查询条件的使用,当涉及到多个字段时,字段类查询的 match 和 term 等API就无能为力了。满足这种多字段检索需要的方式是使用复合查询。
·复合查询是指包含字段类查询或复合查询的类型,主要包括以下几类∶ constant_score query 、 bool query 、 dis_max query 、 function_score query 、 boosting query
这里的话,主要讲一下布尔查询 Bool Query

当我们不需要获取详细的文档信息,只需要获取命中的文档数量时,就可以使用count来获取我们想要的结果。

当我们只需要获取命中文档的指定字段值时,我们可以通过source来指定我们需要es返回的值

ElasticSearch操作之游标查询Scroll Search

一.  什么是游标查询(Scroll)

  顾名思义,相当于用一把游标标记查询的位置.

 

二.  为什么要使用游标查询

  在默认情况下,ES查询每次返回的数量最多只有1W条,且只能是前1W条.

  这意味着,在不修改配置的情况下,想通过分页的方式(如下)拿到1W条之后的数据是做不到的

GET /索引/类型/_search
{
  "size": 10000, 
  "from": 5000, 
  "query": {
    ...   
  }, 
  "aggs": {
    ...  
  }
}

所以自然就有了游标查询.

 

三.  如何使用游标查询

DSL的用法:

GET 索引/类型/_search?scroll=1m
{
  "size": 10000,
  "query": {
    "match_all": {}
  }
}

1m表示:过期时间1分钟

 

查询结果的第一行会有:

  "_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBAAAAAAABO-dFmRFSU9NM1VNU2JxNG9UUlNnSmpXMVEAAAAAAL7J_hYxT0dJOVJVMVFxU2I0N2xCR2IyVzJnAAAAAAC-    SmQWWk1aN0sxUmRSQmFNS3EwVFh0R0luUQAAAAAAvkplFlpNWjdLMVJkUkJhTUtxMFRYdEdJblE=",

这个_scroll_id就相当于书签,之后的查询带着这个书签,就能根据size不断拿到之后的数据,但是前提是在过期时间之内

 

之后的查询DSL:

GET _search/scroll
{
  "scroll":"1m",
  "scroll_id":"DnF1ZXJ5VGhlbkZldGNoBAAAAAAABPP1FmRFSU9NM1VNU2JxNG9UUlNnSmpXMVEAAAAAAL7OTxYxT0dJOVJVMVFxU2I0N2xCR2IyVzJnAAAAAAC-j70WVVlOZkxQRzJRLXlMRlVMbEQtalBfUQAAAAAAyWm-Fk9HdGx1b3VsUXRLZHV4c1E1OExja0E="
}

将获取的scroll_id作为条件继续查询即可,这里不需要再指定索引和类型,因为scroll_id的唯一性.

在过期时间内,之后的查询的scroll_id是不变的.

 

四.  基于java代码:

     RestClient lowClient = RestClient.builder(new HttpHost("主机",端口))
                .setMaxRetryTimeoutMillis(300000).build();
        RestHighLevelClient client = new RestHighLevelClient(lowClient);
        SearchRequest request = new SearchRequest("索引").types("类型");
     //这里一次查1W条 SearchSourceBuilder sourceBuilder
= new SearchSourceBuilder().size(10000); request.source(builder).searchType(SearchType.DEFAULT); //这句代码就是设置游标查询和过期时间
     request.scroll(TimeValue.timeValueMinutes(
5)); SearchResponse response = client.search(request);      // search     SearchResponse response = client.search(request);     //定义游标
    String scrollId
= null;     if (response != null && response.getHits().getHits().length > 0) {    for (SearchHit hit : response.getHits().getHits()) {   //TODO    }
     //拿到游标    scrollId
= response.getScrollId();     }     //一直查询,直到没有游标返回(查询到底了)     while (true){    if(scrollId == null){   break;    }   SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId).scroll(TimeValue.timeValueMinutes(5));;   response = client.searchScroll(searchScrollRequest);   if (response != null && response.getHits().getHits().length > 0) {   for (SearchHit hit : response.getHits().getHits()) { //TODO   }   scrollId = response.getScrollId();   }else {   break;   }     }

到这里,游标查询的基本操作就OK了.有一点需要注意:

  游标的方式,相当于mysql中生成快照的方式,所以如果在游标查询期间有增删改操作,是获取不到最新的数据的.

以上是关于ElasticSearch查询之——Search API的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch Search API之(Request Body Search 查询主体

ElasticSearch查询之——Search API

Elasticsearch之-查询

elasticsearch 查询 term和match

elasticsearch之分词查询

elasticsearch之高亮查询