Elasticsearch Search API之(Request Body Search 查询主体)

Stella981
• 阅读 728

preference

查询选择副本分片的倾向性(即在一个复制组中选择副本的分片值。默认情况下,es以未指定的顺序从可用的碎片副本中进行选择,副本之间的路由将在集群章节更加详细的介绍 。可以通过该字段指定分片倾向与选择哪个副本。preference可选值:

  • _primary
    只在节点上执行,在6.1.0版本后废弃,将在7.x版本移除。

  • _primary_first
    优先在主节点上执行。在6.1.0版本后废弃,将在7.x版本移除。

  • _replica
    操作只在副本分片上执行,如果有多个副本,其顺序随机。在6.1.0版本后废弃,将在7.x版本移除。

  • _replica_first
    优先在副本分片上执行,如果有多个副本,其顺序随机。在6.1.0版本后废弃,将在7.x版本移除。

  • _only_local
    操作将只在分配给本地节点的分片上执行。_only_local选项保证只在本地节点上使用碎片副本,这对于故障排除有时很有用。所有其他选项不能完全保证在搜索中使用任何特定的碎片副本,而且在索引更改时,这可能意味着如果在处于不同刷新状态的不同碎片副本上执行重复搜索,则可能产生不同的结果。

  • _local
    优先在本地分片上执行。

  • _prefer_nodes:abc,xyz
    优先在指定节点ID的分片上执行,示例中的节点ID为abc、xyz。

  • _shards:2,3
    将操作限制到指定的分片上执行。(这里是2和3)这个首选项可以与其他首选项组合,但必须首先出现_-shards:2,3|_local。

  • _only_nodes:abc,xyz,…
    根据节点ID进行限制。

  • Custom (string) value
    自定义字符串,其路由为 hashcod-e(该值)%赋值组内节点数。例如在web应用中通常以sessionId为倾向值。

explain

是否解释各分数是如何计算的。

1GET /_search 2{ 3    "explain": true, 4    "query" : { 5        "term" : { "user" : "kimchy" } 6    } 7}

version

如果设置为true,则返回每个命中文档的当前版本号。

1GET /_search 2{ 3    "version": true, 4    "query" : { 5        "term" : { "user" : "kimchy" } 6    } 7}

Index Boost

当搜索多个索引时,允许为每个索引配置不同的boost级别。当来自一个索引的点击率比来自另一个索引的点击率更重要时,该属性则非常方便。
使用示例如下:

1GET /_search 2{ 3    "indices_boost" : [ 4        { "alias1" : 1.4 }, 5        { "index*" : 1.3 } 6    ] 7}

min_score

指定返回文档的最小评分,如果文档的评分低于该值,则不返回。

1GET /_search 2{ 3    "min_score": 0.5, 4    "query" : { 5        "term" : { "user" : "kimchy" } 6    } 7}

Named Queries

每个过滤器和查询都可以在其顶级定义中接受_name。搜索响应中每个匹配文档中会增加matched_queries结构体,记录该文档匹配的查询名称。查询和筛选器的标记只对bool查询有意义。
java示例如下:

1public static void testNamesQuery() { 2        RestHighLevelClient client = EsClient.getClient(); 3        try { 4            SearchRequest searchRequest = new SearchRequest(); 5            searchRequest.indices("esdemo"); 6            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); 7            sourceBuilder.query( 8                    QueryBuilders.boolQuery() 9                        .should(QueryBuilders.termQuery("context", "fox").queryName("q1")) 10                        .should(QueryBuilders.termQuery("context", "brown").queryName("q2")) 11                    ); 12            searchRequest.source(sourceBuilder); 13            SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT); 14            System.out.println(result); 15        } catch (Throwable e) { 16            e.printStackTrace(); 17        } finally { 18            EsClient.close(client); 19        } 20    }

返回结果如下:

1{ 10    "hits":{ 19                "_source":{ 20                    "context":"My quick brown as fox eats rabbits on a regular basis.", 21                    "title":"Keeping pets healthy" 22                }, 23                "matched_queries":[ 24                    "q1", 25                    "q2" 26                ] 27            } 41        ] 42    } 43}

正如上面所说,每个匹配文档中都包含matched_queries,表明该文档匹配的是哪个查询条件。

Inner hits

用于定义内部嵌套层的返回规则,其inner hits支持如下选项:

  • from 用于内部匹配的分页。

  • size 用于内部匹配的分页,size。

  • sort 排序策略。

  • name 为内部嵌套层定义的名称。
    该部分示例将在下节重点阐述。

field collapsing(字段折叠)

允许根据字段值折叠搜索结果。折叠是通过在每个折叠键上只选择排序最高的文档来完成的。有点类似于聚合分组,其效果类似于按字段进行分组,默认命中的文档列表第一层由该字段的第一条信息,也可以通过允许根据字段值折叠搜索结果。折叠是通过在每个折叠键上只选择排序最高的文档来完成的。例如下面的查询为每个用户检索最佳twee-t,并按喜欢的数量对它们进行排序。
下面首先通过示例进行展示field colla-psing的使用。
1)首先查询发的推特内容中包含elast-icsearch的推文:

1GET /twitter/_search 2{ 3    "query": { 4        "match": { 5            "message": "elasticsearch" 6        } 7    }, 8    "collapse" : { 9        "field" : "user"  10    }, 11    "sort": ["likes"] 12}

返回结果:

_`1{

13        "hits":[
14            {
15                "_index":"mapping_field_collapsing_twitter",
16                "_type":"_doc",
17                "_id":"OYnecmcB-IBeb8B-bF2X",
18                "_score":null,
19                "source":{
20                    "message":"to be a elasticsearch",
21                    "user":"user2",
22                    "likes":3
23                },
24                "sort":[
25                    3
26                ]
27            },
84        ]
85    }
86}`

首先上述会列出所有用户的推特,如果只想每个用户只显示一条推文,并且点赞率最高,或者每个用户只显示2条推文呢?这个时候,按字段折叠就闪亮登场了。java demo如下:

1public static void search_field_collapsing() { 2        RestHighLevelClient client = EsClient.getClient(); 3        try { 4            SearchRequest searchRequest = new SearchRequest(); 5            searchRequest.indices("mapping_field_collapsing_twitter"); 6            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); 7            sourceBuilder.query( 8                    QueryBuilders.matchQuery("message","elasticsearch") 9            ); 10            sourceBuilder.sort("likes", SortOrder.DESC); 11            CollapseBuilder collapseBuilder = new CollapseBuilder("user"); 12            sourceBuilder.collapse(collapseBuilder); 13            searchRequest.source(sourceBuilder); 14            SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT); 15            System.out.println(result); 16        } catch (Throwable e) { 17            e.printStackTrace(); 18        } finally { 19            EsClient.close(client); 20        } 21    }

其结果如下:

1{ 10    "hits":{ 11  13        "hits":[ 14            { 15                "_index":"mapping_field_collapsing_twitter", 16                "_type":"_doc", 17                "_id":"OYnecmcB-IBeb8B-bF2X", 18                "_score":null, 19                "_source":{ 20                    "message":"to be a elasticsearch", 21                    "user":"user2", 22                    "likes":3 23                }, 24                "fields":{ 25                    "user":[ 26                        "user2" 27                    ] 28                }, 29                "sort":[ 30                    3 31                ] 32            }, 33            { 34                "_index":"mapping_field_collapsing_twitter", 35                "_type":"_doc", 36                "_id":"OInecmcB-IBeb8B-bF2G", 37                "_score":null, 38                "_source":{ 39                    "message":"elasticsearch is very high", 40                    "user":"user1", 41                    "likes":3 42                }, 43                "fields":{ 44                    "user":[ 45                        "user1" 46                    ] 47                }, 48                "sort":[ 49                    3 50                ] 51            } 52        ] 53    } 54}

上面的示例只返回了每个用户的第一条数据,如果需要每个用户返回2条数据呢?可以通过inner_hit来设置。

1public static void search_field_collapsing() { 2        RestHighLevelClient client = EsClient.getClient(); 3        try { 4            SearchRequest searchRequest = new SearchRequest(); 5            searchRequest.indices("mapping_field_collapsing_twitter"); 6            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); 7            sourceBuilder.query( 8                    QueryBuilders.matchQuery("message","elasticsearch") 9            ); 10            sourceBuilder.sort("likes", SortOrder.DESC); 11            CollapseBuilder collapseBuilder = new CollapseBuilder("user"); 12 13            InnerHitBuilder collapseHitBuilder = new InnerHitBuilder("collapse_inner_hit"); 14            collapseHitBuilder.setSize(2); 15            collapseBuilder.setInnerHits(collapseHitBuilder); 16            sourceBuilder.collapse(collapseBuilder); 17 18            searchRequest.source(sourceBuilder); 19            SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT); 20            System.out.println(result); 21        } catch (Throwable e) { 22            e.printStackTrace(); 23        } finally { 24            EsClient.close(client); 25        } 26    }

返回结果如下:

1{ 2    "took":42, 3    "timed_out":false, 4    "_shards":{ 5        "total":5, 6        "successful":5, 7        "skipped":0, 8        "failed":0 9    }, 10    "hits":{ 11        "total":5, 12        "max_score":null, 13        "hits":[ 14            { 15                "_index":"mapping_field_collapsing_twitter", 16                "_type":"_doc", 17                "_id":"OYnecmcB-IBeb8B-bF2X", 18                "_score":null, 19                "_source":{ 20                    "message":"to be a elasticsearch", 21                    "user":"user2", 22                    "likes":3 23                }, 24                "fields":{ 25                    "user":[ 26                        "user2" 27                    ] 28                }, 29                "sort":[ 30                    3 31                ], 32                "inner_hits":{ 33                    "collapse_inner_hit":{ 34                        "hits":{ 35                            "total":2, 36                            "max_score":0.19363807, 37                            "hits":[ 38                                { 39                                    "_index":"mapping_field_collapsing_twitter", 40                                    "_type":"_doc", 41                                    "_id":"OonecmcB-IBeb8B-bF2q", 42                                    "_score":0.19363807, 43                                    "_source":{ 44                                        "message":"to be elasticsearch", 45                                        "user":"user2", 46                                        "likes":3 47                                    } 48                                }, 49                                { 50                                    "_index":"mapping_field_collapsing_twitter", 51                                    "_type":"_doc", 52                                    "_id":"OYnecmcB-IBeb8B-bF2X", 53                                    "_score":0.17225473, 54                                    "_source":{ 55                                        "message":"to be a elasticsearch", 56                                        "user":"user2", 57                                        "likes":3 58                                    } 59                                } 60                            ] 61                        } 62                    } 63                } 64            }, 65            { 66                "_index":"mapping_field_collapsing_twitter", 67                "_type":"_doc", 68                "_id":"OInecmcB-IBeb8B-bF2G", 69                "_score":null, 70                "_source":{ 71                    "message":"elasticsearch is very high", 72                    "user":"user1", 73                    "likes":3 74                }, 75                "fields":{ 76                    "user":[ 77                        "user1" 78                    ] 79                }, 80                "sort":[ 81                    3 82                ], 83                "inner_hits":{ 84                    "collapse_inner_hit":{ 85                        "hits":{ 86                            "total":3, 87                            "max_score":0.2876821, 88                            "hits":[ 89                                { 90                                    "_index":"mapping_field_collapsing_twitter", 91                                    "_type":"_doc", 92                                    "_id":"O4njcmcB-IBeb8B-Rl2H", 93                                    "_score":0.2876821, 94                                    "_source":{ 95                                        "message":"elasticsearch is high db", 96                                        "user":"user1", 97                                        "likes":1 98                                    } 99                                }, 100                                { 101                                    "_index":"mapping_field_collapsing_twitter", 102                                    "_type":"_doc", 103                                    "_id":"N4necmcB-IBeb8B-bF0n", 104                                    "_score":0.2876821, 105                                    "_source":{ 106                                        "message":"very likes elasticsearch", 107                                        "user":"user1", 108                                        "likes":1 109                                    } 110                                } 111                            ] 112                        } 113                    } 114                } 115            } 116        ] 117    } 118}

此时,返回结果是两级,第一级,还是每个用户第一条消息,然后再内部中嵌套inner_hits。

Search After

Elasticsearch支持的第三种分页获取方式,该方法不支持跳转页面。
es支持的分页方式目前已知:

  1. 通过from和size,当时当达到深度分页时,成本变的非常高昂,故es提供了索引参数:index.max_result_window来控制(from + size)的最大值,默认为10000,超过该值后将报错。

  2. 通过scroll滚动API,该方式类似于快照的工作方式,不具备实时性,并且滚动上下文的存储需要耗费一定的性能。
    本节将介绍第3种分页方式,search after,基于上一页查询的结果进行下一页数据的查询。基本思想是选择一组排序字段,能做到全局唯一。es的排序查询响应结果中会返回sort数组,包含本排序字段的最大值,下一页查询将该组字段当成查询条件,es在此数据的基础下返回下一批合适的数据。
    java示例如下:

1public static void search_search_after() { 2        RestHighLevelClient client = EsClient.getClient(); 3        try { 4            SearchRequest searchRequest = new SearchRequest(); 5            searchRequest.indices("mapping_search_after"); 6            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder(); 7            sourceBuilder.query( 8                    QueryBuilders.termQuery("user","user2") 9            ); 10            sourceBuilder.size(1); 11            sourceBuilder.sort("id", SortOrder.ASC); 12            searchRequest.source(sourceBuilder); 13            SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT); 14            System.out.println(result); 15            if(hasHit(result)) { // 如果本次匹配到数据 16                // 省略处理数据逻辑 17                // 继续下一批查询 18                // result.getHits(). 19                int length = result.getHits().getHits().length; 20                SearchHit aLastHit = result.getHits().getHits()[length - 1]; 21                //开始下一轮查询 22                sourceBuilder.searchAfter(aLastHit.getSortValues()); 23                result = client.search(searchRequest, RequestOptions.DEFAULT); 24                System.out.println(result); 25            } 26        } catch (Throwable e) { 27            e.printStackTrace(); 28        } finally { 29            EsClient.close(client); 30        } 31    } 32    private static boolean hasHit(SearchResponse result) { 33        return !( result.getHits() == null || 34                result.getHits().getHits() == null || 35                result.getHits().getHits().length < 1 ); 36    }


更多文章请关注微信公众号:

Elasticsearch Search API之(Request Body Search 查询主体)

广告:作者新书《RocketMQ技术内幕》已上市

Elasticsearch Search API之(Request Body Search 查询主体)

《RocketMQ技术内幕》已出版上市,目前可在主流购物平台(京东、天猫等)购买,本书从源码角度深度分析了RocketMQ NameServer、消息发送、消息存储、消息消费、消息过滤、主从同步HA、事务消息;在实战篇重点介绍了RocketMQ运维管理界面与当前支持的39个运维命令;并在附录部分罗列了RocketMQ几乎所有的配置参数。本书得到了RocketMQ创始人、阿里巴巴Messaging开源技术负责人、Linux OpenMessaging 主席的高度认可并作序推荐。目前是国内第一本成体系剖析RocketMQ的书籍。

本文分享自微信公众号 - 中间件兴趣圈(dingwpmz_zjj)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
5个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
3年前
NoSQL之MongoDB
1.mongodb介绍2.mongodb安装3.连接mongodb4.mongodb用户管理5.mongodb创建集合、数据管理6.php的mongodb扩展7.php的mongo扩展8.mongodb副本集介绍9.mongodb副本集搭建10.mongodb副本集测试11.mongodb分片介
Wesley13 Wesley13
3年前
MongoDB 副本集之入门篇
前言:mongodb因为高性能、高可用性、支持分片等特性,作为非关系型数据库被大家广泛使用。其高可用性主要是体现在mongodb的副本集上面(可以简单理解为一主多从的集群),本篇文章主要从副本集介绍、本地搭建副本集、副本集读写数据这三个方面来带大家认识下mongodb副本集。一、mongodb副本集介绍—
Stella981 Stella981
3年前
MongoDb分片集群认证
本文主要基于已经搭建好的未认证集群,结合上篇Mongodb副本集分片集群模式环境部署(https://www.cnblogs.com/woxingwoxue/p/9875878.html),MongoDb分片集群认证几个主要流程1.在分片集群环境中,副本集内成员之间需要用keyFile认证,mongos与配置服务器,副本集之间也要keyFi
Wesley13 Wesley13
3年前
ELK初探
EKL核心组成1.ElasticSearch开源分布式搜索引擎,他的特点是分布式、零配置、自动发现、索引自动分片,索引副本机制,restful接口,多数据源,自动搜索负载。安装ElasticSearch  高可用,易扩展,支持集群(cluster),分片和复制(sharding和replicas)验证启动:curlXGETht
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Elasticsearch文档读写模型实现原理
ES系列基于ElasticSearch6.4.x版本。1、简介ElasticSearch的存储设计天生就是分布式的。每个索引被分成多个分片(默认每个索引含5个主分片(primaryshard)),每个主分片又可以有多个副本。当一个文档被添加或删除时(主分片中新增或删除),其对应的复制分片之间必须保持同步。如果我们不这样做,那么对于同一个文档的检索请
Wesley13 Wesley13
3年前
MongoDB构建分片集群及分片管理
一、副本的概念1.主从复制和副本集区别2、副本集的两种类型3、三种角色:4、缺点二、分片概念1.数据块2.平衡器三、分片集群包含的组件四、构建分片群集拓扑1.解压软件包