Elasticsearch Java Rest Client API

Posted 尚墨1111

tags:

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

Elasticsearch Java Rest Client API

全部参考自博客,只是当存储
参考博客:https://www.cnblogs.com/reycg-blog/p/9946821.html


1 SearchAPI——Search Request

searchRequest 用来完成和搜索文档,聚合,建议等相关的任何操作同时也提供各种方式来完成对查询结果的高亮操作

最基本的查询操作如下

SearchRequest searchRequest = new SearchRequest(); 
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); 
searchSourceBuilder.query(QueryBuilders.matchAllQuery()); // 添加 match_all 查询
searchRequest.source(searchSourceBuilder); // 将 SearchSourceBuilder  添加到 SeachRequest 中

1.1 可选参数

SearchRequest searchRequest = new SearchRequest("posts");  // 设置搜索的 index
searchRequest.types("doc");  // 设置搜索的 type

除了配置 indextype 外,还有一些其他的可选参数

searchRequest.routing("routing"); // 设置 routing 参数
searchRequest.preference("_local");  // 配置搜索时偏爱使用本地分片,默认是使用随机分片

什么是 routing 参数?

当索引一个文档的时候,文档会被存储在一个主分片上。在存储时一般都会有多个主分片。Elasticsearch 如何知道一个文档应该放置在哪个分片呢?这个过程是根据下面的这个公式来决定的:

shard = hash(routing) % number_of_primary_shards
  • routing 是一个可变值,默认是文档的 _id ,也可以设置成一个自定义的值
  • number_of_primary_shards 是主分片数量

所有的文档 API 都接受一个叫做 routing 的路由参数,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。

1.2 使用 SearchSourceBuilder

对搜索行为的配置可以使用 SearchSourceBuilder 来完成,来看一个实例

SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();  // 默认配置
sourceBuilder.query(QueryBuilders.termQuery("user", "kimchy")); // 设置搜索,可以是任何类型的 QueryBuilder
sourceBuilder.from(0); // 起始 index
sourceBuilder.size(5); // 大小 size
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); // 设置搜索的超时时间

设置完成后,就可以添加到 SearchRequest 中。

SearchRequest searchRequest = new SearchRequest();
searchRequest.source(sourceBuilder);

1.3 构建查询条件

查询请求是通过使用 QueryBuilder 对象来完成的,并且支持 Query DSL

DSL (domain-specific language) 领域特定语言,是指专注于某个应用程序领域的计算机语言。

— 百度百科

可以使用构造函数来创建 QueryBuilder

MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("user", "kimchy"); 

QueryBuilder 创建后,就可以调用方法来配置它的查询选项:

matchQueryBuilder.fuzziness(Fuzziness.AUTO);  // 模糊查询
matchQueryBuilder.prefixLength(3); // 前缀查询的长度
matchQueryBuilder.maxExpansions(10); // max expansion 选项,用来控制模糊查询

也可以使用QueryBuilders 工具类来创建 QueryBuilder 对象。这个类提供了函数式编程风格的各种方法用来快速创建 QueryBuilder 对象。

QueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "kimchy")
                                        .fuzziness(Fuzziness.AUTO)
                                                .prefixLength(3)
                                                .maxExpansions(10);

fuzzy-matching 拼写错误时的匹配:

好的全文检索不应该是完全相同的限定逻辑,相反,可以扩大范围来包括可能的匹配,从而根据相关性得分将更好的匹配放在前面。
例如,搜索 quick brown fox 时会匹配一个包含 fast brown foxes 的文档

不论什么方式创建的 QueryBuilder ,最后都需要添加到 SearchSourceBuilder` 中

searchSourceBuilder.query(matchQueryBuilder);

构建查询 文档中提供了一个丰富的查询列表,里面包含各种查询对应的QueryBuilder 对象以及QueryBuilder helper 方法,大家可以去参考。

指定排序

SearchSourceBuilder 允许添加一个或多个SortBuilder 实例。这里包含 4 种特殊的实现, (Field-, Score-, GeoDistance-ScriptSortBuilder)

sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); // 根据分数 _score 降序排列 (默认行为)
sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));  // 根据 id 降序排列

1.4 过滤数据源

默认情况下,查询请求会返回文档的内容 _source ,当然我们也可以配置它。例如,禁止对 _source 的获取

sourceBuilder.fetchSource(false);

也可以使用通配符模式以更细的粒度包含或排除特定的字段:

String[] includeFields = new String[] {"title", "user", "innerObject.*"};
String[] excludeFields = new String[] {"_type"};
sourceBuilder.fetchSource(includeFields, excludeFields);

1.5 其他

高亮请求

可以通过在 SearchSourceBuilder 上设置 HighlightBuilder 完成对结果的高亮,而且可以配置不同的字段具有不同的高亮行为。

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
HighlightBuilder highlightBuilder = new HighlightBuilder(); 
HighlightBuilder.Field highlightTitle =
        new HighlightBuilder.Field("title"); // title 字段高亮
highlightTitle.highlighterType("unified");  // 配置高亮类型
highlightBuilder.field(highlightTitle);  // 添加到 builder
HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
highlightBuilder.field(highlightUser);
searchSourceBuilder.highlighter(highlightBuilder);

聚合请求

要实现聚合请求分两步

  1. 创建合适的 AggregationBuilder`
  2. 作为参数配置在 SearchSourceBuilder` 上
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
TermsAggregationBuilder aggregation = AggregationBuilders.terms("by_company")
        .field("company.keyword");
aggregation.subAggregation(AggregationBuilders.avg("average_age")
        .field("age"));
searchSourceBuilder.aggregation(aggregation);

建议请求 Requesting Suggestions

SuggestionBuilder 实现类是由 SuggestBuilders 工厂类来创建的。

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
SuggestionBuilder termSuggestionBuilder =
    SuggestBuilders.termSuggestion("user").text("kmichy"); 
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("suggest_user", termSuggestionBuilder); 
searchSourceBuilder.suggest(suggestBuilder);

1.6 对请求和聚合分析

分析 API 可用来对一个特定的查询操作中的请求和聚合进行分析,此时要将SearchSourceBuilder 的 profile标志位设置为 true

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.profile(true);

只要 SearchRequest 执行完成,对应的 SearchResponse 响应中就会包含 分析结果

1.7 查询响应 SearchResponse

查询执行完成后,会返回 SearchResponse 对象,并在对象中包含查询执行的细节和符合条件的文档集合。

归纳一下, SerchResponse 包含的信息如下

  • 请求本身的信息,如 HTTP 状态码,执行时间,或者请求是否超时
RestStatus status = searchResponse.status(); // HTTP 状态码
TimeValue took = searchResponse.getTook(); // 查询占用的时间
Boolean terminatedEarly = searchResponse.isTerminatedEarly(); // 是否由于 SearchSourceBuilder 中设置 terminateAfter 而过早终止
boolean timedOut = searchResponse.isTimedOut(); // 是否超时
  • 查询影响的分片数量的统计信息,成功和失败的分片
int totalShards = searchResponse.getTotalShards();
int successfulShards = searchResponse.getSuccessfulShards();
int failedShards = searchResponse.getFailedShards();
for (ShardSearchFailure failure : searchResponse.getShardFailures()) {
    // failures should be handled here
}

1.8 检索 SearchHits

要访问返回的文档,首先要在响应中获取其中的 SearchHits

SearchHits hits = searchResponse.getHits();

SearchHits 中包含了所有命中的全局信息,如查询命中的数量或者最大分值:

long totalHits = hits.getTotalHits();
float maxScore = hits.getMaxScore();

查询的结果嵌套在 SearchHits 中,可以通过遍历循环获取

SearchHit[] searchHits = hits.getHits();
for (SearchHit hit : searchHits) {
    // do something with the SearchHit
}

SearchHit 提供了如 indextypedocId 和每个命中查询的分数

String index = hit.getIndex();
String type = hit.getType();
String id = hit.getId();
float score = hit.getScore();

而且,还可以获取到文档的源数据,以 JSON-String 形式或者 key-value map 对的形式。在 map 中,字段可以是普通类型,或者是列表类型,嵌套对象。

String sourceAsString = hit.getSourceAsString();
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
String documentTitle = (String) sourceAsMap.get("title");
List<Object> users = (List<Object>) sourceAsMap.get("user");
Map<String, Object> innerObject = (Map<String, Object>) sourceAsMap.get("innerObject");

2 Search API 查询关系

上面的 QueryBuilderSearchSourceBuilderSearchRequest 之间都是嵌套关系,为此我专门整理了一个关系图,以便更清楚的确认它们之间的关系。感兴趣的同学可用此图与前面的 API 进行对应,以加深理解。

3 Building Queries

由上图看出, QueryBuilder 是整个查询操作的核心,决定了查询什么样的数据和期望得到什么结果这些核心的问题。

QueryBuilder 只是一个接口,需要具体的实体类才可以。那么如何创建 QueryBuilder 的实例呢?有两种方式

  • 通过 QueryBuilder 实现类的构造函数
  • 使用 QueryBuilders 工具类创建

3.1 匹配所有的查询

查询语句如下

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

对应的 QueryBuilder Class 为 MatchAllQueryBuilder

具体方法为 QueryBuilders.matchAllQuery()

全文查询 Full Text Queries

像使用 match 或者 query_string 这样的高层查询都属于全文查询,

  • 查询 日期(date) 或整数(integer) 字段,会将查询字符串分别作为日期或整数对待。
  • 查询一个( not_analyzed )未分析的精确值字符串字段,会将整个查询字符串作为单个词项对待。
  • 查询一个( analyzed )已分析的全文字段,会先将查询字符串传递到一个合适的分析器,然后生成一个供查询的词项列表

组成了词项列表,后面就会对每个词项逐一执行底层查询,将查询结果合并,并且为每个文档生成最终的相关度评分。

3.2 Match查询

match 查询的单个词的步骤是什么?

  1. 检查字段类型,查看字段是 analyzed, not_analyzed
  2. 分析查询字符串,如果只有一个单词项, match 查询在执行时就会是单个底层的 term 查询
  3. 查找匹配的文档,会在倒排索引中查找匹配文档,然后获取一组包含该项的文档
  4. 为每个文档评分

构建 Match 查询

match 查询可以接受 text/numeric/dates 格式的参数,分析,并构建一个查询。

GET /_search
{
    "query": {
        "match" : {
            "message" : "this is a test"
        }
    }
}

上面的实例中 message 是一个字段名。

对应的 QueryBuilder class : MatchQueryBuilder

具体方法 : QueryBuilders.matchQuery()

3.3 全文查询 API 列表

全部的 API 列表如下(链接均指向 elasticsearch 官网)

Search QueryQueryBuilder ClassMethod in QueryBuilders
MatchMatchQueryBuilderQueryBuilders.matchQuery()
Match PhraseMatchPhraseQueryBuilderQueryBuilders.matchPhraseQuery()
Match Phrase PrefixMatchPhrasePrefixQueryBuilderQueryBuilders.matchPhrasePrefixQuery()
Multi MatchMultiMatchQueryBuilderQueryBuilders.multiMatchQuery()
Common TermsCommonTermsQueryBuilderQueryBuilders.commonTermsQuery()
Query StringQueryStringQueryBuilderQueryBuilders.queryStringQuery()
Simple Query StringSimpleQueryStringBuilderQueryBuilders.simpleQueryStringQuery()

3.4 基于词项的查询

这种类型的查询不需要分析,它们是对单个词项操作,只是在倒排索引中查找准确的词项(精确匹配)并且使用 TF/IDF 算法为每个包含词项的文档计算相关度评分 _score

Term

term 查询可用作精确值匹配,精确值的类型则可以是数字,时间,布尔类型,或者是那些 not_analyzed 的字符串。

对应的 QueryBuilder class 是TermQueryBuilder

具体方法是 QueryBuilders.termQuery()

Terms

terms 查询允许指定多个值进行匹配。如果这个字段包含了指定值中的任何一个值,就表示该文档满足条件。

对应的 QueryBuilder class 是 TermsQueryBuilder

具体方法是 QueryBuilders.termsQuery()

Wildcard

wildcard 通配符查询是一种底层基于词的查询,它允许指定匹配的正则表达式。而且它使用的是标准的 shell 通配符查询:

  • ? 匹配任意字符
  • * 匹配 0 个或多个字符

wildcard 需要扫描倒排索引中的词列表才能找到所有匹配的词,然后依次获取每个词相关的文档 ID。

由于通配符和正则表达式只能在查询时才能完成,因此查询效率会比较低,在需要高性能的场合,应当谨慎使用。

对应的 QueryBuilder class 是 WildcardQueryBuilder

具体方法是 QueryBuilders.wildcardQuery()

Es的模糊查询,match,match_phrase、wildcard的区别

1、match查询:会先对搜索词进行分词,比如“白雪公主和苹果”,会分成“白雪”“公主”“苹果”。含有相关内容的字段,都会被检索出来。

2、match_phrase查询:match_phrase与slop一起用,能保证分词间的邻近关系,slop参数告诉match_phrase查询词条能够相隔多远时仍然将文档视为匹配,默认是0。为0时 必须相邻才能被检索出来。
例如下面的语句,会把“白雪公主吃苹果”也能检索出来

{
  "query": {
    "match_phrase": {
        "content" : {
            "query" : "白雪公主和苹果""slop" : 1
        }
    }
  }
}

3、wildcard查询:是使用通配符进行查询,其中?代表任意一个字符*代表任意的一个或多个字符。
下面的语句会把包含“公主”这个词语的内容检索出来。

{
"query": {  
         "wildcard": { 
             "title":"\\*公主\\*" 
             }
       }
}

3.5 基于词项 API 列表

Search QueryQueryBuilder ClassMethod in QueryBuilders
TermTermQueryBuilderQueryBuilders.termQuery()
TermsTermsQueryBuilderQueryBuilders.termsQuery()
RangeRangeQueryBuilderQueryBuilders.rangeQuery()
ExistsExistsQueryBuilderQueryBuilders.existsQuery()
PrefixPrefixQueryBuilderQueryBuilders.prefixQuery()
WildcardWildcardQueryBuilderQueryBuilders.wildcardQuery()
RegexpRegexpQueryBuilderQueryBuilders.regexpQuery()
FuzzyFuzzyQueryBuilderQueryBuilders.fuzzyQuery()
TypeTypeQueryBuilderQueryBuilders.typeQuery()
IdsIdsQueryBuilderQueryBuilders.idsQuery()

3.6 复合查询

复合查询会将其他的复合查询或者叶查询包裹起来,以嵌套的形式展示和执行,得到的结果也是对各个子查询结果和分数的合并。可以分为下面几种:

  • constant_score query

    经常用在使用 filter 的场合,所有匹配的文档分数都是一个不变的常量

  • bool query

    可以将多个叶查询和组合查询再组合起来,可接受的参数如下

  • must : 文档必须匹配这些条件才能被包含进来

  • must_not 文档必须不匹配才能被包含进来

  • should 如果满足其中的任何语句,都会增加分数;即使不满足,也没有影响

  • filter 以过滤模式进行,不评分,但是必须匹配

  • dis_max query

    叫做分离最大化查询,它会将任何与查询匹配的文档都作为结果返回,但是只是将其中最佳匹配的评分作为最终的评分返回。

  • function_score query

    允许为每个与主查询匹配的文档应用一个函数,可用来改变甚至替换原始的评分

  • boosting query

    用来控制(提高或降低)复合查询中子查询的权重。

3.7 复合查询列表

Search QueryQueryBuilder ClassMethod in QueryBuilders
Constant ScoreConstantScoreQueryBuilderQueryBuilders.constantScoreQuery()
BoolBoolQueryBuilderQueryBuilders.boolQuery()
Dis MaxDisMaxQueryBuilderQueryBuilders.disMaxQuery()
Function ScoreFunctionScoreQueryBuilderQueryBuilders.functionScoreQuery()
BoostingBoostingQueryBuilderQueryBuilders.boostingQuery()

3.8 特殊查询

Wrapper Query

这里比较重要的一个是 Wrapper Query,是说可以接受任何其他 base64 编码的字符串作为子查询。

主要应用场合就是在 Rest High-Level REST client 中接受 json 字符串作为参数。比如使用 gson 等 json 库将要查询的语句拼接好,直接塞到 Wrapper Query 中查询就可以了,非常方便。

Wrapper Query 对应的 QueryBuilder class 是WrapperQueryBuilder

具体方法是 QueryBuilders.wrapperQuery()

3.9 Spring Boot中集成Elasticsearch:

参考文章:SpringBoot+Elasticsearch

使用方法:Spring Data Elasticsearch Repositories,非常类似于mysql的查询。

1、首先需要进行各种配置

2、再自己定义一个接口,并继承ElasticsearchRepository,这里的Repository相当于DAO,操作mysql还是elasticsearch都是一样的

Commodity是商品的实体类,对应数据库表

//在代码中就是ESClientUtil
@Repository以上是关于Elasticsearch Java Rest Client API的主要内容,如果未能解决你的问题,请参考以下文章

ElasticSearch04_elasticsearch-Rest-Client整合SpringBoot中使用保存数据利用JAVA代码操作es

ElasticSearch04_elasticsearch-Rest-Client整合SpringBoot中使用保存数据利用JAVA代码操作es

ElasticSearch04_elasticsearch-Rest-Client整合SpringBoot中使用保存数据利用JAVA代码操作es

Elasticsearch java api操作(Java High Level Rest Client)

encrypted communication elasticsearch java rest client

商城项目19_elasticsearch-Rest-Client整合SpringBoot中使用保存数据利用JAVA代码操作es