ElasticSearch核心查询API汇总

本文汇总整理了ElasticSearch比较常用的API,建议收藏转发,以备您后续查阅参考。

match_all查询所有

match_all 查询简单地匹配所有文档。在没有指定查询方式时,它是默认的查询方式:

{ "match_all": {}}

match全文搜索

无论你在任何字段上进行的是全文搜索还是精确查询,match 查询是你可用的标准查询。如果你在一个全文字段上使用 match 查询,在执行查询前,它将用正确的分析器去分析查询字符串:

{ "match": { "tweet": "About Search" }}

如果在一个精确值的字段上使用它,例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:

{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}

对于精确值查询,你可能需要使用 filter 语句来取代 query,因为 filter 将会被缓存。

multi_match多字段查询

multi_match 查询可以在多个字段上执行相同的 match 查询:

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
}
}

range区间查询

range 查询找出那些落在指定区间内的数字或者时间:

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
}
}

被允许的操作符如下:

操作符

说明

gt

大于

gte

大于等于

lt

小于

lte

小于等于

term精确查询

term 查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些 not_analyzed 的字符串:

{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}

term 查询对于输入的文本不分析,所以它将给定的值进行精确查询。

terms多值查询

terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}

和 term 查询一样,terms 查询对于输入的文本不分析。它查询那些精确匹配的值(包括在大小写、重音、空格等方面的差异)。

exists 查询和 missing 查询

exists 查询和 missing 查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:

{
    "exists":   {
        "field":    "title"
}
}

这些查询经常用于某个字段有值的情况和某个字段缺值的情况。

match_phase习语匹配

match_phase习语匹配,查询确切的phase,在对查询字段定义了分词器的情况下,会使用分词器对输入进行分词,然后返回满足下述两个条件的document:

  1. match_phase中的所有term都出现在待查询字段之中。
  2. 待查询字段之中的所有term都必须和match_phase具有相同的顺序。

如:

{ "foo":"I just said hello world" }
{ "foo":"Hello world" }
{ "foo":"World Hello" }

使用match_phase:

{
  "query": {
    "match_phrase": {
      "foo": "Hello World"
    }
  }
}

结果会返回前两条文档。

bool查询(组合查询)

你可以用 bool 查询来实现你的需求。这种查询将多查询组合在一起,成为用户自己想要的布尔查询。它接收以下参数:

参数

说明

must

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

must_not

文档 必须不匹配这些条件才能被包含进来。

should

如果满足这些语句中的任意语句,将增加 _score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。

filter

必须匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

举例

查找 title 字段匹配 how to make millions 并且不被标识为 spam 的文档。那些被标识为 starred 或在2014之后的文档,将比另外那些文档拥有更高的排名。如果 两者 都满足,那么它排名将更高:

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }},
            { "range": { "date": { "gte": "2014-01-01" }}}
        ]
}
}

filter过滤器查询

过滤器查询的字段必须要匹配,但是不参与算分。

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "range": { "date": { "gte": "2014-01-01" }} 
        }
}
}

range 查询已经从 should 语句中移到 filter 语句。通过将 range 查询移到 filter 语句中,我们将它转成不评分的查询,将不再影响文档的相关性排名。由于它现在是一个不评分的查询,可以使用各种对 filter 查询有效的优化手段来提升性能。

如果你需要通过多个不同的标准来过滤你的文档,bool 查询本身也可以被当做不评分的查询。简单地将它放置到 filter 语句中并在内部构建布尔逻辑:

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "bool": {
              "must": [
                  { "range": { "date": { "gte": "2014-01-01" }}},
                  { "range": { "price": { "lte": 29.99 }}}
              ],
              "must_not": [
                  { "term": { "category": "ebooks" }}
              ]
          }
        }
}
}

将 bool 查询包裹在 filter 语句中,我们可以在过滤标准中增加布尔逻辑。

分页

和SQL使用 LIMIT 关键字返回单个 page 结果的方法相同,Elasticsearch 接受 from 和 size 参数:

size

显示应该返回的结果数量,默认是 10

from

显示应该跳过的初始结果数量,默认是 0

如果每页展示 5 条结果,可以用下面方式请求得到 1 到 3 页的结果:

curl -X GET "localhost:9200/_search?size=5&pretty"
curl -X GET "localhost:9200/_search?size=5&from=5&pretty"
curl -X GET "localhost:9200/_search?size=5&from=10&pretty"

考虑到分页过深以及一次请求太多结果的情况,结果集在返回之前先进行排序。 但请记住一个请求经常跨越多个分片,每个分片都产生自己的排序结果,这些结果需要进行集中排序以保证整体顺序是正确的。web 搜索引擎对任何查询都不要返回超过 1000 个结果。

排序

在 Elasticsearch 中, 相关性得分 由一个浮点数进行表示,并在搜索结果中通过 _score 参数返回, 默认排序是 _score 降序。

curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
    "query" : {
        "bool" : {
            "filter" : { "term" : { "user_id" : 1 }}
        }
    },
    "sort": { "date": { "order": "desc" }}
}

相关性介绍

每个文档都有相关性评分,用一个正浮点数字段 _score 来表示 。 _score 的评分越高,相关性越高。

查询语句会为每个文档生成一个 _score 字段。评分的计算方式取决于查询类型 不同的查询语句用于不同的目的: fuzzy 查询会计算与关键词的拼写相似程度,terms 查询会计算 找到的内容与关键词组成部分匹配的百分比,但是通常我们说的 relevance 是我们用来计算全文本字段的值相对于全文本检索词相似程度的算法。

Elasticsearch 的相似度算法被定义为检索词频率/反向文档频率, TF/IDF ,包括以下内容:

检索词频率

检索词在该字段出现的频率?出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。

反向文档频率

每个检索词在索引中出现的频率?频率越高,相关性越低。检索词出现在多数文档中会比出现在少数文档中的权重更低。

字段长度准则

字段的长度是多少?长度越长,相关性越低。 检索词出现在一个短的 title 要比同样的词出现在一个长的 content 字段权重更大。

单个查询可以联合使用 TF/IDF 和其他方式,比如短语查询中检索词的距离或模糊查询里的检索词相似度。

相关性并不只是全文本检索的专利。也适用于 yes|no 的子句,匹配的子句越多,相关性评分越高。

如果多条查询子句被合并为一条复合查询语句,比如 bool 查询,则每个查询子句计算得出的评分会被合并到总的相关性评分中。

最后:整合使用RestHighLevelClient

导入依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

配置yml

#集成elasticsearch
spring:
  elasticsearch:
    rest:
      uris: http://192.168.93.128:9200

注入使用

package com.test;

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
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.SpringRunner;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 中恒
 */
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestESAPI {

    @Autowired
    private RestHighLevelClient client;

    @Test
    public void test1() throws Exception{
        boolean ping = client.ping(RequestOptions.DEFAULT);
        System.out.println(ping);
    }

    @Test
    public void test2() throws Exception {
        SearchRequest searchRequest = new SearchRequest();

        //构建查询条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        List<QueryBuilder> querys = new ArrayList<>();
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();

        MatchQueryBuilder logDetailQuery = QueryBuilders.matchQuery("log_detail", "系统软件");
        querys.add(logDetailQuery);

        TermQueryBuilder logActionQuery = QueryBuilders.termQuery("log_action", "表单提交成功");
        querys.add(logActionQuery);

        TermQueryBuilder logCodeQuery = QueryBuilders.termQuery("log_code", "1550277");
        querys.add(logActionQuery);

        RangeQueryBuilder dateQuery = QueryBuilders.rangeQuery("create_date").from("2019-07-30",true).to("2019-08-01",true);
        querys.add(dateQuery);

        //构建bool查询
        for (int i = 0; i < querys.size(); i++) {
            boolQuery.must(querys.get(i));
        }

        //设置查询条件
        sourceBuilder.query(boolQuery);
        //设置排序
        //sourceBuilder.sort("log_code", SortOrder.DESC);
        //设置分页参数
        sourceBuilder.from(1);
        sourceBuilder.size(5);
        searchRequest.source(sourceBuilder);

        //获取查询结果
        SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = response.getHits();

        System.out.println("查询数量:" + (hits.getHits().length));
        hits.forEach(hit -> {
            Map<String, Object> map = hit.getSourceAsMap();
            System.out.println(map);
        });
    }
}

内容出处:,

声明:本网站所收集的部分公开资料来源于互联网,转载的目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。如果您发现网站上有侵犯您的知识产权的作品,请与我们取得联系,我们会及时修改或删除。文章链接:http://www.yixao.net/tech/29740.html

发表评论

登录后才能评论