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

2023-06-25,,

一、概述

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();
}

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  

009-elasticsearch5.4.3【三】搜索概述-查询模型、分页、ES数据类型的相关教程结束。

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

下载本文的Word格式文档,以方便收藏与打印。