• 009-elasticsearch5.4.3【三】搜索概述-查询模型、分页、ES数据类型


    一、概述

    1、查询模型

    搜索API允许用户执行搜索查询并返回与查询匹配的搜索匹配。它可以跨一个或多个索引以及跨一种或多种类型执行。可以使用查询Java API提供查询。搜索请求的主体是使用SearchSourceBuilder构建的。这是一个例子:

    import org.elasticsearch.action.search.SearchResponse;
    import org.elasticsearch.action.search.SearchType;
    import org.elasticsearch.index.query.QueryBuilders.*;
    SearchResponse response
    = client.prepareSearch("index1", "index2") .setTypes("type1", "type2") .setSearchType(SearchType.DFS_QUERY_THEN_FETCH) .setQuery(QueryBuilders.termQuery("multi", "test")) // Query .setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18)) // Filter .setFrom(0).setSize(60).setExplain(true) .get();

    注意,所有参数都是可选的。这是您可以编写的最小的搜索调用:

    // MatchAll on the whole cluster with all default options
    SearchResponse response = client.prepareSearch().get();

    虽然Java API定义了其他搜索类型QUERY_AND_FETCH和DFS_QUERY_AND_FETCH,但这些模式是内部优化,不应由API用户明确指定。

    更多API

    2、分页【from+size,scroll游标】

    from+size

    SearchResponse response = client.prepareSearch("indexName")
    .setQuery(QueryBuilders.matchAllQuery())
    .setFrom(10)   //跳过前10个文档
    .setSize(20)   //获取20个文档
    .execute().actionGet();
    response.getHits().totalHits()可以统计当前匹配到的结果数

    ES为了避免深分页,不允许使用分页(from&size)查询10000条以后的数据,因此如果要查询第10000条以后的数据,要使用ES提供的 scroll(游标) 来查询

      假设取的页数较大时(深分页),如请求第20页,Elasticsearch不得不取出所有分片上的第1页到第20页的所有文档,并做排序,最终再取出from后的size条结果作爲最终的返回值

      假设你有16个分片,则需要在coordinate node彙总到 shards* (from+size)条记录,即需要16*(20+10)记录后做一次全局排序

      所以,当索引非常非常大(千万或亿),是无法使用from + size 做深分页的,分页越深则越容易OOM,即便不OOM,也很消耗CPU和内存资源

      因此ES使用index.max_result_window:10000作爲保护措施 ,即默认 from + size 不能超过10000,虽然这个参数可以动态修改,也可以在配置文件配置,但是最好不要这麽做,应该改用ES游标来取得数据

    scroll游标原理

      可以把 scroll 理解爲关系型数据库里的 cursor,因此,scroll 并不适合用来做实时搜索,而更适用于后台批处理任务,比如群发

      scroll 具体分爲初始化和遍历两步

      初始化时将所有符合搜索条件的搜索结果缓存起来,可以想象成快照

      在遍历时,从这个快照里取数据

      也就是说,在初始化后对索引插入、删除、更新数据都不会影响遍历结果

      游标可以增加性能的原因,是因为如果做深分页,每次搜索都必须重新排序,非常浪费,使用scroll就是一次把要用的数据都排完了,分批取出,因此比使用from+size还好
    更多API

    java示例

    import static org.elasticsearch.index.query.QueryBuilders.*;
    
    QueryBuilder qb = termQuery("multi", "test");
    
    SearchResponse scrollResp = client.prepareSearch(test)
            .addSort(FieldSortBuilder.DOC_FIELD_NAME, SortOrder.ASC)
            .setScroll(new TimeValue(60000))
            .setQuery(qb)
            .setSize(100).get(); //max of 100 hits will be returned for each scroll
    //Scroll until no hits are returned
    do {
        for (SearchHit hit : scrollResp.getHits().getHits()) {
            //Handle the hit...
        }
    
        scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet();
    } while(scrollResp.getHits().getHits().length != 0); // Zero hits mark the end of the scroll and the while loop.

    3、多搜索

    更多API

    SearchRequestBuilder srb1 = client
        .prepareSearch().setQuery(QueryBuilders.queryStringQuery("elasticsearch")).setSize(1);
    SearchRequestBuilder srb2 = client
        .prepareSearch().setQuery(QueryBuilders.matchQuery("name", "kimchy")).setSize(1);
    
    MultiSearchResponse sr = client.prepareMultiSearch()
            .add(srb1)
            .add(srb2)
            .get();
    
    // You will get all individual responses from MultiSearchResponse#getResponses()
    long nbHits = 0;
    for (MultiSearchResponse.Item item : sr.getResponses()) {
        SearchResponse response = item.getResponse();
        nbHits += response.getHits().getTotalHits();
    }
    View Code

    4、提前终止

    在达到每个分片收集的最大文档数查询执行将提前终止时,如果设置,您将能够通过在SearchResponse onject中请求isTerminatedEarly()来检查操作是否提前终止:

    SearchResponse sr = client.prepareSearch(INDEX)
        .setTerminateAfter(1000)    
        .get();
    
    if (sr.isTerminatedEarly()) {
        // We finished early
    }

    5、查询模板

    参看地址

    二、ES数据类型

    2.1、映射(Mapping)

      相当于数据表的表结构。ElasticSearch中的映射(Mapping)用来定义一个文档,可以定义所包含的字段以及字段的类型、分词器及属性等等。

    映射可以分为动态映射和静态映射。

      动态映射 (dynamic mapping):在关系数据库中,需要事先创建数据库,然后在该数据库实例下创建数据表,然后才能在该数据表中插入数据。而ElasticSearch中不需要事先定义映射(Mapping),文档写入ElasticSearch时,会根据文档字段自动识别类型,这种机制称之为动态映射。

      静态映射 :在ElasticSearch中也可以事先定义好映射,包含文档的各个字段及其类型等,这种方式称之为静态映射。

    2.2、数据类型

    一级分类 二级分类 具体类型 说明
    核心类型 字符串类型 string,text,keyword

    1、string是2.x版本的,从ElasticSearch 5.x开始不再支持string,由text和keyword类型替代
    2、text :当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型。设置text类型以后,字段内容会被分析,在生成倒排索引以前,字符串会被分析器分成一个一个词项。text类型的字段不用于排序,很少用于聚合。text类型不能用来排序和聚合
    3、keyword :类型适用于索引结构化的字段,比如email地址、主机名、状态码和标签。如果字段需要进行过滤(比如查找已发布博客中status属性为published的文章)、排序、聚合。keyword类型的字段只能通过精确值搜索到。该类型不需要进行分词,可以被用来检索过滤、排序和聚合,keyword类型自读那只能用本身来进行检索(不可用text分词后的模糊检索)
     

    没有string类型了,全部用text,而且text的,自动加了keyword属性,如果精确查找,后面直接加keyword就ok,例如:  name.keyword='中国'   

    整数类型 integer,long,short,byte 在满足需求的情况下,尽可能选择范围小的数据类型。比如,某个字段的取值最大值不会超过100,那么选择byte类型即可。字段的长度越短,索引和搜索的效率越高。
    浮点类型 double,float,half_float,scaled_float 对于float、half_float和scaled_float,-0.0和+0.0是不同的值,使用term查询查找-0.0不会匹配+0.0,同样range查询中上边界是-0.0不会匹配+0.0,下边界是+0.0不会匹配-0.0。
    其中scaled_float,比如价格只需要精确到分,price为57.34的字段缩放因子为100,存起来就是5734 优先考虑使用带缩放因子的scaled_float浮点类型。
    逻辑类型 boolean 逻辑类型(布尔类型)可以接受true/false/”true”/”false”值 
    日期类型 date 日期类型表示格式可以是以下几种:
    (1)日期格式的字符串,比如 “2018-01-13” 或 “2018-01-13 12:10:30”
    (2)long类型的毫秒数( milliseconds-since-the-epoch,epoch就是指UNIX诞生的UTC时间1970年1月1日0时0分0秒)
    (3)integer的秒数(seconds-since-the-epoch)
    ElasticSearch 内部会将日期数据转换为UTC,并存储为milliseconds-since-the-epoch的long型整数。
    范围类型 range  
    二进制类型 binary 二进制字段是指用base64来表示索引中存储的二进制数据,可用来存储二进制形式的数据,例如图像。
    默认情况下,该类型的字段只存储不索引。二进制类型只支持index_name属性。
    复合类型 数组类型 array 在ElasticSearch中,没有专门的数组(Array)数据类型,但是,在默认情况下,任意一个字段都可以包含0或多个值,这意味着每个字段默认都是数组类型,只不过,数组类型的各个元素值的数据类型必须相同。在ElasticSearch中,数组是开箱即用的(out of box),不需要进行任何配置,就可以直接使用。
    在同一个数组中,数组元素的数据类型是相同的,ElasticSearch不支持元素为多个数据类型:[ 10, “some string” ],常用的数组类型是:
    (1)字符数组: [ “one”, “two” ]
    (2)整数数组: productid:[ 1, 2 ]
    (3)对象(文档)数组: “user”:[ { “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }],ElasticSearch内部把对象数组展开为 {“user.name”: [“Mary”, “John”], “user.age”: [12,10]}
    对象类型 object JSON天生具有层级关系,文档会包含嵌套的对象
    嵌套类型 nested 用于JSON数组
    地理类型 地理坐标类型 geo_point 用于经纬度坐标;
    地理地图 geo_shape 用于类似于多边形的复杂形状
    特殊类型 IP类型 ip ip类型的字段用于存储IPv4或者IPv6的地址
    范围类型 completion 提供自动补全建议
    令牌计数类型 token_count 用于统计做了标记的字段的index数目,该值会一直增加,不会因为过滤条件而减少。
    附件类型 attachment 采用 mapper-attachments 插件,可支持 attachments 索引,例如 Microsoft Office 格式,Open Document 格式,ePub, HTML 等。
    抽取类型 percolator  
  • 相关阅读:
    Linux_23 DNS 正向解析区域、反向解析区域;主/从;子域;基本安全控制
    Linux_22 加密和解密及OpenSSL
    Linux_21 日志系统、ssh服务、系统安装及系统故障排除
    Linux_20 子网划分
    Akavache简明使用指南
    Oracle存储过程解析XML内容
    docker部署微服务不支持中文字体的解决方案
    Three.js
    Three.js
    [Linux] vim状态栏配置
  • 原文地址:https://www.cnblogs.com/bjlhx/p/8508186.html
Copyright © 2020-2023  润新知