java 通配符查找文件-excel通配符查找替换
本节将详细介绍es Search API的查询主体,定制化查询条件的实现主体。
query
搜索请求体中查询条件使用es DSL查询语法来定义。通过使用query来定义查询体。
1GET /_search
2{
3 "query" : {
4 "term" : { "user" : "kimchy" }
5 }
6}
From / Size
es的一种分页语法。通过使用from和size参数来对结果集进行分页。
from设置第一条数据的偏移量。size设置返回的条数(针对每个分片生效),由于es天生就是分布式的,通过设置主分片个数来进行数据水平切分,一个查询请求通常需要从多个后台节点(分片)进行数据汇聚。
From/Size方式会遇到分布式存储的一个共性问题:深度分页,也就是页数越大需要访问的数据则越大。es提供了另外一种分页方式,滚动API(Scroll),后续会详细分析。
注意:from + size 不能超过index.max_result_window配置项的值,其默认值为10000。
sort (排序)
与传统关系型数据库类似,es支持根据一个或多个字段进行排序,同时支持asc升序或desc降序。另外es可以按照_score(基于得分)的排序,默认值。
如果使用了排序,响应结果中每一条命中数据将包含一个响应字段sort,其类型为Object[],表示该文档当前的排序值,该值在ES支持的第三种分页方式Search After中会使用到。
排序顺序
es提供了两种排序顺序,SortOrder.ASC(asc)升序、SortOrder.DESC(desc)降序,如果排序类型为_score,其默认排序顺序为降序(desc),如果排序类型为字段,则默认排序顺序为升序(asc)。
排序模型选型
es支持按数组或多值字段进行排序。模式选项控制选择的数组值,以便对它所属的文档进行排序。模式选项可以有以下值:
如果是一个数组类型的值参与排序,通常会对该数组元素进行一些计算得出一个最终参与排序的值,例如取平均数、最大值、最小值、求和等运算。es通过排序模型mode来指定。
嵌套字段排序
es还支持在一个或多个嵌套对象内部的字段进行排序。一个嵌套查询提包含如下选项(参数):
1"sort" : [
2 {
3 "parent.child.age" : { // @1
4 "mode" : "min",
5 "order" : "asc",
6 "nested": { // @2
7 "path": "parent",
8 "filter": {
9 "range": {"parent.age": {"gte": 21}}
10 },
11 "nested": { // @3
12 "path": "parent.child",
13 "filter": {
14 "match": {"parent.child.name": "matt"}
15 }
16 }
17 }
18 }
19 }
20]
代码@1:排序字段名,支持级联表示字段名。代码@2:通过nested属性定义排序嵌套语法,其中path定义当前的嵌套层级,filter定义过滤上下文。@3内部可以再通过nested属性再次嵌套定义。
missing values
由于es的索引,类型下的字段可以在索引文档时动态增加,那如果有些文档没有包含排序字段,这部分文档的顺序如何确定呢?es通过missing属性来确定,其可选值为:
ignoring unmapped fields
默认情况下,如果排序字段为未映射的字段将抛出异常。可通过unmapped_type来忽略该异常,该参数指定一个类型,也就是告诉ES如果未找该字段名的映射,就认为该字段是一个unmapped_type指定的类型,所有文档都未存该字段的值。
Geo sorting
地图类型排序,该部分将在后续专题介绍geo类型时讲解。
字段过滤
默认情况下,对命中的结果会返回_source字段下的所有内容。字段过滤机制允许用户按需要返回_source字段里面部分字段。其过滤设置机制已在Elasticsearch Document Get API详解、原理与示例中已详细介绍,在这里就不重复介绍了。
Doc Value Fields
使用方式如下:
1GET /_search
2{
3 "query" : {
4 "match_all": {}
5 },
6 "docvalue_fields" : [
7 {
8 "field": "my_date_field",
9 "format": "epoch_millis"
10
11 }
12 ]
13}
通过使用docvalue_fields指定需要转换的字段与格式,它对于在映射文件中定义stored=false的字段同样生效。字段支持用通配符,例如"field":"myfield*"。
docvalue_fields中指定的字段并不会改变_souce字段中的值,而是使用fields返回值进行额外返回。
java实例代码片段如下(完整的Demo示例将在文末给出):
1SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
2sourceBuilder.query(QueryBuilders.termQuery("user", "dingw"))
3 .sort(new FieldSortBuilder("post_date").order(SortOrder.DESC))
4 .docValueField("post_date", "epoch_millis")
其返回结果如下:
{
"took":88,
"timed_out":false,
"_shards":{
"total":5,
"successful":5,
"skipped":0,
"failed":0
},
"hits":{
"total":2,
"max_score":null,
"hits":[
{
"_index":"twitter",
"_type":"_doc",
"_id":"11",
"_score":null,
"_source":{
"post_date":"2009-11-19T14:12:12",
"message":"test bulk update",
"user":"dingw"
},
"fields":{
"post_date":[
"1258639932000"
]
},
"sort":[
1258639932000
]
},
{
"_index":"twitter",
"_type":"_doc",
"_id":"12",
"_score":null,
"_source":{
"post_date":"2009-11-18T14:12:12",
"message":"test bulk",
"user":"dingw"
},
"fields":{
"post_date":[
"1258553532000"
]
},
"sort":[
1258553532000
]
}
]
}
}
Post Filter
post filter对查询条件命中后的文档再做一次筛选。
1GET /shirts/_search
2{
3 "query": {
4 "bool": {
5 "filter": {
6 "term": { "brand": "gucci" } // @1
7 }
8 }
9 },
10 "post_filter": { // @2
11 "term": { "color": "red" }
12 }
13}
首先根据@1条件对索引进行检索,然后得到匹配的文档后,再利用@2过滤条件对结果再一次筛选。
Highlighting
查询结果高亮显示。
Es支持的高亮分析器
用于对查询结果中对查询关键字进行高亮显示,高亮显示查询条件在查询结果中匹配的部分。
注意:高亮显示器在提取要高亮显示的术语时不能反映查询的布尔逻辑。因此对于一些复杂的布尔查询(例如嵌套的布尔查询,或使用minimum_should_match等查询)可能高亮显示会出现一些误差。
高亮显示需要字段的实际内容。如果字段没有存储(映射没有将store设置为true),则从_source中提取相关字段。
es支持三种高亮显示工具,通过为每个字段指定type来使用。
Offsets Strategy
获取偏移量策略。高亮显示要解决的一个核心就是高亮显示的词根以及该词根的位置(位置与偏移量)。
ES中提供了3中获取偏移量信息(Offsets)的策略:
高亮显示配置项
高亮显示的全局配置会被字段级别的覆盖。
高亮显示demo
1public static void testSearch_highlighting() {
2 RestHighLevelClient client = EsClient.getClient();
3 try {
4 SearchRequest searchRequest = new SearchRequest();
5 searchRequest.indices("map_highlighting_01");
6 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
7 sourceBuilder.query(
8 // QueryBuilders.matchAllQuery()
9 QueryBuilders.termQuery("context", "身份证")
10 );
11
12 HighlightBuilder highlightBuilder = new HighlightBuilder();
13 highlightBuilder.field("context");
14
15 sourceBuilder.highlighter(highlightBuilder);
16 searchRequest.source(sourceBuilder);
17 System.out.println(client.search(searchRequest, RequestOptions.DEFAULT));
18 } catch (Exception e) {
19 // TODO: handle exception
20 }
21 }
其返回值如下:
1{
10 "hits":{
11
13 "hits":[
14 {
19 "_source":{
20 "context":"城中西路可以受理外地二代身份证的办理。"
21 },
22 "highlight":{ // @1
23 "context":[
24 "城中西路可以受理外地二代身份证的办理。"
25 ]
26 }
27 }
28 ]
29 }
30}
这里主要对highlight再做一次说明,其中每一个字段返回的内容是对应原始数据的子集,最多fragmentSize个待关键字的匹配条目,通常,在页面上显示文本时,应该用该字段取代原始值,这样才能有高亮显示的效果。
Rescoring
重打分机制。一个查询首先使用高效的算法查找文档,然后对返回结果的top n 文档运用另外的查询算法,通常这些算法效率低效但能提供匹配精度。resoring查询与原始查询分数的合计方式如下:
Search Type
查询类型,默认值为query_then_fetch。
scroll
滚动查询。es另外一种分页方式。虽然搜索请求返回结果的单个页面,但scroll API可以用于从单个搜索请求检索大量结果(甚至所有结果),这与在传统数据库上使用游标的方式非常相似。
scroll api不用于实时用户请求,而是用于处理大量数据,例如为了将一个索引的内容重新索引到具有不同配置的新索引中。
如何使用scroll API
scroll API使用分为两步:
1、第一步,首先通过scroll参数,指定该滚动查询(类似于数据库的游标的存活时间)
1POST /twitter/_search?scroll=1m
2{
3 "size": 100,
4 "query": {
5 "match" : {
6 "title" : "elasticsearch"
7 }
8 }
9}
该方法会返回一个重要的参数scrollId。
2、第二步,使用该scrollId去es服务器拉取下一批(下一页数据)
1POST /_search/scroll
2{
3 "scroll" : "1m",
4 "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
5}
循环第三步,可以循环批量处理数据。
3、第三步,清除scrollIdjava 通配符查找文件,类似于清除数据库游标,快速释放资源。
1DELETE /_search/scroll
2{
3 "scroll_id" : "DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ=="
4}
下面给出scoll api的java版本示例程序
1public static void testScoll() {
2 RestHighLevelClient client = EsClient.getClient();
3 String scrollId = null;
4 try {
5 System.out.println("step 1 start ");
6 // step 1 start
7 SearchRequest searchRequest = new SearchRequest();
8 searchRequest.indices("map_highlighting_01");
9 SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
10 sourceBuilder.query(
11 QueryBuilders.termQuery("context", "身份证")
12 );
13 searchRequest.source(sourceBuilder);
14 searchRequest.scroll(TimeValue.timeValueMinutes(1));
15 SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
16 scrollId = result.getScrollId();
17 // step 1 end
18
19 // step 2 start
20 if(!StringUtils.isEmpty(scrollId)) {
21 System.out.println("step 2 start ");
22 SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
23 scrollRequest.scroll(TimeValue.timeValueMinutes(1));
24 while(true) { //循环遍历
25 SearchResponse scollResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
26 if(scollResponse.getHits().getHits() == null ||
27 scollResponse.getHits().getHits().length < 1) {
28 break;
29 }
30 scrollId = scollResponse.getScrollId();
31 // 处理文档
32 scrollRequest.scrollId(scrollId);
33 }
34 // step 2 end
35 }
36 System.out.println(result);
37 } catch (Exception e) {
38 e.printStackTrace();
39 } finally {
40 if(!StringUtils.isEmpty(scrollId)) {
41 System.out.println("step 3 start ");
42 // step 3 start
43 ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
44 clearScrollRequest.addScrollId(scrollId);
45 try {
46 client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
47 } catch (IOException e) {
48 // TODO Auto-generated catch block
49 e.printStackTrace();
50 }
51 // step 3 end
52 }
53 }
54
55 }
这里重点阐述一下第一次查询时,不仅返回scrollId,也会返回第一批数据。
Keeping the search context alive
scroll参数(传递给搜索请求和每个滚动请求)告诉es它应该保持搜索上下文活动多长时间。只需要足够长的时间来处理前一批结果。
每个scroll请求(带有scroll参数)设置一个新的过期时间。如果scroll请求没有传入scroll,那么搜索上下文将作为scroll请求的一部分被释放。
scroll其内部实现类似于快照java 通配符查找文件,当第一次收到一个scroll请求时,就会为该搜索上下文所匹配的结果创建一个快照,随后文档的变化并不会反映到该API的结果。
sliced scroll
对于返回大量文档的scroll查询,可以将滚动分割为多个可以独立使用的片,通过slice指定。例如:
1GET /twitter/_search?scroll=1m // @1
2{
3 "slice": { // @11
4 "id": 0, // @12
5 "max": 2 // @13
6 },
7 "query": {
8 "match" : {
9 "title" : "elasticsearch"
10 }
11 }
12}
13GET /twitter/_search?scroll=1m // @2
14{
15 "slice": {
16 "id": 1,
17 "max": 2
18 },
19 "query": {
20 "match" : {
21 "title" : "elasticsearch"
22 }
23 }
24}
@1,@2两个并列的查询,按分片去查询。
@11:通过slice定义分片查询。
@12:该分片查询的ID。
@13:本次查询总片数。
这个机制非常适合多线程处理数据。
具体分片机制是,首先将请求转发到各分片节点,然后在每个节点使用匹配到的文档(hashcode(_uid)%slice片数),然后各分片节点返回数据到协调节点。也就是默认情况下,分片是根据文档的_uid,为了提高分片过程,可以通过如下方式进行优化,并指定分片字段。
注意,默认slice片数最大为1024,可以通过索引设置项index.max_slices_per_scroll来改变默认值。例如:
1GET /twitter/_search?scroll=1m
2{
3 "slice": {
4 "field": "date",
5 "id": 0,
6 "max": 10
7 },
8 "query": {
9 "match" : {
10 "title" : "elasticsearch"
11 }
12 }
13}