“failed”:0
},
“hits”:{
“total”:1,
“max_score”:0.2876821,
“hits”:[
{
“_index”:“map_highlighting_01”,
“_type”:“_doc”,
“_id”:“erYsbmcBeEynCj5VqVTI”,
“_score”:0.2876821,
“_source”:{
“context”:“城中西路可以受理外地二代身份证的办理。”
},
“highlight”:{ // @1
“context”:[
“城中西路可以受理外地二代身份证的办理。”
]
}
}
]
}
}
这里主要对highlight再做一次说明,其中每一个字段返回的内容是对应原始数据的子集,最多fragmentSize个待关键字的匹配条目,通常,在页面上显示文本时,应该用该字段取代原始值,这样才能有高亮显示的效果。
8、Rescoring
重打分机制。一个查询首先使用高效的算法查找文档,然后对返回结果的top n 文档运用另外的查询算法,通常这些算法效率低效但能提供匹配精度。
resoring查询与原始查询分数的合计方式如下:
- total
两个评分相加
- multiply
将原始分数乘以rescore查询分数。用于函数查询重定向。
- avg
取平均数
- max
取最大值
- min
取最小值。
9、Search Type
查询类型,可选值:QUERY_THEN_FETCH、QUERY_AND_FETCH、DFS_QUERY_THEN_FETCH。默认值:query_then_fetch。
-
QUERY_THEN_FETCH:首先根据路由算法向相关分片(多个)发送请求,此时只返回documentId与一些必要信息(例如用于排序等),然后对各个分片的结果进行汇聚,排序,然后选取客户端指定需要获取的数据条数(top n),然后根据documentId再向各个分片请求具体的文档信息。
-
QUERY_AND_FETCH:在5.4.x版本开始废弃,是直接向各个分片节点请求数据,每个分片返回客户端请求数量的文档信息,然后汇聚全部返回给客户端,返回的数据为客户端请求数量size * (路由后的分片数量)。
-
DFS_QUERY_THEN_FETCH:在开始向各个节点发送请求之前,会进行一次词频、相关性的计算,后续流程与QUERY_THEN_FETCH相同,可以看出,该查询类型的文档相关性会更高,但性能比QUERY_THEN_FETCH要差。
10、scroll
滚动查询。es另外一种分页方式。虽然搜索请求返回结果的单个“页面”,但scroll API可以用于从单个搜索请求检索大量结果(甚至所有结果),这与在传统数据库上使用游标的方式非常相似。scroll api不用于实时用户请求,而是用于处理大量数据,例如为了将一个索引的内容重新索引到具有不同配置的新索引中。
10.1 如何使用scroll API
scroll API使用分为两步:
1、第一步,首先通过scroll参数,指定该滚动查询(类似于数据库的游标的存活时间)
POST /twitter/_search?scroll=1m
{
“size”: 100,
“query”: {
“match” : {
“title” : “elasticsearch”
}
}
}
该方法会返回一个重要的参数:scrollId。
2、第二步,使用该scrollId去es服务器拉取下一批(下一页数据)
POST /_search/scroll
{
“scroll” : “1m”,
“scroll_id” : “DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==”
}
循环第三步,可以循环批量处理数据。
3、第三步,清除scrollId,类似于清除数据库游标,快速释放资源。
DELETE /_search/scroll
{
“scroll_id” : “DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAAD4WYm9laVYtZndUQlNsdDcwakFMNjU1QQ==”
}
下面给出scoll api的java版本示例程序:
public static void testScoll() {
RestHighLevelClient client = EsClient.getClient();
String scrollId = null;
try {
System.out.println("step 1 start ");
// step 1 start
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(“map_highlighting_01”);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
QueryBuilders.termQuery(“context”, “身份证”)
);
searchRequest.source(sourceBuilder);
searchRequest.scroll(TimeValue.timeValueMinutes(1));
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
scrollId = result.getScrollId();
// step 1 end
// step 2 start
if(!StringUtils.isEmpty(scrollId)) {
System.out.println("step 2 start ");
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
scrollRequest.scroll(TimeValue.timeValueMinutes(1));
while(true) { //循环遍历
SearchResponse scollResponse = client.scroll(scrollRequest, RequestOptions.DEFAULT);
if(scollResponse.getHits().getHits() == null ||
scollResponse.getHits().getHits().length < 1) {
break;
}
scrollId = scollResponse.getScrollId();
// 处理文档
scrollRequest.scrollId(scrollId);
}
// step 2 end
}
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
} finally {
if(!StringUtils.isEmpty(scrollId)) {
System.out.println("step 3 start ");
// step 3 start
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollId);
try {
client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// step 3 end
}
}
}
这里重点阐述一下第一次查询时,不仅返回scrollId,也会返回第一批数据。
10.2 Keeping the search context alive
scroll参数(传递给搜索请求和每个滚动请求)告诉Elasticsearch它应该保持搜索上下文活动多长时间。它的值(例如1m,参见Time unitsedit)不需要足够长的时间来处理所有数据——它只需要足够长的时间来处理前一批结果。每个scroll请求(带有scroll参数)设置一个新的过期时间。如果scroll请求没有传入scroll,那么搜索上下文将作为scroll请求的一部分被释放。scroll其内部实现类似于快照,当第一次收到一个scroll请求时,就会为该搜索上下文所匹配的结果创建一个快照,随后文档的变化并不会反映到该API的结果。
10.3 sliced scroll
对于返回大量文档的scroll查询,可以将滚动分割为多个可以独立使用的片,通过slice指定。
例如:
GET /twitter/_search?scroll=1m // @1
{
“slice”: { // @11
“id”: 0, // @12
“max”: 2 // @13
},
“query”: {
“match” : {
“title” : “elasticsearch”
}
}
}
GET /twitter/_search?scroll=1m // @2
{
“slice”: {
“id”: 1,
“max”: 2
},
“query”: {
“match” : {
“title” : “elasticsearch”
}
}
}
@1,@2两个并列的查询,按分片去查询。
@11:通过slice定义分片查询。
@12:该分片查询的ID。
@13:本次查询总片数。
这个机制非常适合多线程处理数据。
具体分片机制是,首先将请求转发到各分片节点,然后在每个节点使用匹配到的文档(hashcode(_uid)%slice片数),然后各分片节点返回数据到协调节点。也就是默认情况下,分片是根据文档的_uid,为了提高分片过程,可以通过如下方式进行优化,并指定分片字段。
-
分片字段类型为数值型。
-
字段的doc_values设置为true。
-
每个文档中都索引了该字段。
-
该字段值只在创建时赋值,并不会更新。
-
字段的基数应该很高(相当于数据库索引选择度),这样能确保每个片返回的数据相当,数据分布较均匀。
注意,默认slice片数最大为1024,可以通过索引设置项index.max_slices_per_scroll来改变默认值。
例如:
GET /twitter/_search?scroll=1m
{
“slice”: {
“field”: “date”,
“id”: 0,
“max”: 10
},
“query”: {
“match” : {
“title” : “elasticsearch”
}
}
}
11、preference
查询选择副本分片的倾向性(即在一个复制组中选择副本的分片值。默认情况下,Elasticsearch以未指定的顺序从可用的碎片副本中进行选择,副本之间的路由将在集群章节更加详细的介绍 。可以通过该字段指定分片倾向与选择哪个副本。
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*,x*yz,…
根据节点ID进行限制。
- Custom (string) value
自定义字符串,其路由为 hashcode(该值)%赋值组内节点数。例如在web应用中通常以sessionId为倾向值。
12、explain
是否解释各分数是如何计算的。
GET /_search
{
“explain”: true,
“query” : {
“term” : { “user” : “kimchy” }
}
}
13、version
如果设置为true,则返回每个命中文档的当前版本号。
GET /_search
{
“version”: true,
“query” : {
“term” : { “user” : “kimchy” }
}
}
14、Index Boost
当搜索多个索引时,允许为每个索引配置不同的boost级别。当来自一个索引的点击率比来自另一个索引的点击率更重要时,该属性则非常方便。
使用示例如下:
GET /_search
{
“indices_boost” : [
{ “alias1” : 1.4 },
{ “index*” : 1.3 }
]
}
15、min_score
指定返回文档的最小评分,如果文档的评分低于该值,则不返回。
GET /_search
{
“min_score”: 0.5,
“query” : {
“term” : { “user” : “kimchy” }
}
}
16、Named Queries
每个过滤器和查询都可以在其顶级定义中接受_name。搜索响应中每个匹配文档中会增加matched_queries结构体,记录该文档匹配的查询名称。查询和筛选器的标记只对bool查询有意义。
java示例如下:
public static void testNamesQuery() {
RestHighLevelClient client = EsClient.getClient();
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(“esdemo”);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
QueryBuilders.boolQuery()
.should(QueryBuilders.termQuery(“context”, “fox”).queryName(“q1”))
.should(QueryBuilders.termQuery(“context”, “brown”).queryName(“q2”))
);
searchRequest.source(sourceBuilder);
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(result);
} catch (Throwable e) {
e.printStackTrace();
} finally {
EsClient.close(client);
}
}
返回结果如下:
{
“took”:4,
“timed_out”:false,
“_shards”:{
“total”:5,
“successful”:5,
“skipped”:0,
“failed”:0
},
“hits”:{
“total”:2,
“max_score”:0.5753642,
“hits”:[
{
“_index”:“esdemo”,
“_type”:“matchquerydemo”,
“_id”:“2”,
“_score”:0.5753642,
“_source”:{
“context”:“My quick brown as fox eats rabbits on a regular basis.”,
“title”:“Keeping pets healthy”
},
“matched_queries”:[
“q1”,
“q2”
]
},
{
“_index”:“esdemo”,
“_type”:“matchquerydemo”,
“_id”:“1”,
“_score”:0.39556286,
“_source”:{
“context”:“Brown rabbits are commonly seen brown.”,
“title”:“Quick brown rabbits”
},
“matched_queries”:[
“q2”
]
}
]
}
}
正如上面所说,每个匹配文档中都包含matched_queries,表明该文档匹配的是哪个查询条件。
17、Inner hits
用于定义内部嵌套层的返回规则,其inner hits支持如下选项:
-
from 用于内部匹配的分页。
-
size 用于内部匹配的分页,size。
-
sort 排序策略。
-
name 为内部嵌套层定义的名称。
该部分示例将在下节重点阐述。
18、field collapsing(字段折叠)
允许根据字段值折叠搜索结果。折叠是通过在每个折叠键上只选择排序最高的文档来完成的。有点类似于聚合分组,其效果类似于按字段进行分组,默认命中的文档列表第一层由该字段的第一条信息,也可以通过允许根据字段值折叠搜索结果。折叠是通过在每个折叠键上只选择排序最高的文档来完成的。例如,下面的查询为每个用户检索最佳tweet,并按喜欢的数量对它们进行排序。
下面首先通过示例进行展示field collapsing的使用。
1)首先查询发的推特内容中包含elasticsearch的推文:
GET /twitter/_search
{
“query”: {
“match”: {
“message”: “elasticsearch”
}
},
“collapse” : {
“field” : “user”
},
“sort”: [“likes”]
}
返回结果:
{
“took”:8,
“timed_out”:false,
“_shards”:{
“total”:5,
“successful”:5,
“skipped”:0,
“failed”:0
},
“hits”:{
“total”:5,
“max_score”:null,
“hits”:[
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OYnecmcB-IBeb8B-bF2X”,
“_score”:null,
“_source”:{
“message”:“to be a elasticsearch”,
“user”:“user2”,
“likes”:3
},
“sort”:[
3
]
},
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OonecmcB-IBeb8B-bF2q”,
“_score”:null,
“_source”:{
“message”:“to be elasticsearch”,
“user”:“user2”,
“likes”:3
},
“sort”:[
3
]
},
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OInecmcB-IBeb8B-bF2G”,
“_score”:null,
“_source”:{
“message”:“elasticsearch is very high”,
“user”:“user1”,
“likes”:3
},
“sort”:[
3
]
},
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“O4njcmcB-IBeb8B-Rl2H”,
“_score”:null,
“_source”:{
“message”:“elasticsearch is high db”,
“user”:“user1”,
“likes”:1
},
“sort”:[
1
]
},
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“N4necmcB-IBeb8B-bF0n”,
“_score”:null,
“_source”:{
“message”:“very likes elasticsearch”,
“user”:“user1”,
“likes”:1
},
“sort”:[
1
]
}
]
}
}
首先上述会列出所有用户的推特,如果只想每个用户只显示一条推文,并且点赞率最高,或者每个用户只显示2条推文呢?
这个时候,按字段折叠就闪亮登场了。
java demo如下:
public static void search_field_collapsing() {
RestHighLevelClient client = EsClient.getClient();
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(“mapping_field_collapsing_twitter”);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
QueryBuilders.matchQuery(“message”,“elasticsearch”)
);
sourceBuilder.sort(“likes”, SortOrder.DESC);
CollapseBuilder collapseBuilder = new CollapseBuilder(“user”);
sourceBuilder.collapse(collapseBuilder);
searchRequest.source(sourceBuilder);
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(result);
} catch (Throwable e) {
e.printStackTrace();
} finally {
EsClient.close(client);
}
}
其结果如下:
{
“took”:22,
“timed_out”:false,
“_shards”:{
“total”:5,
“successful”:5,
“skipped”:0,
“failed”:0
},
“hits”:{
“total”:5,
“max_score”:null,
“hits”:[
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OYnecmcB-IBeb8B-bF2X”,
“_score”:null,
“_source”:{
“message”:“to be a elasticsearch”,
“user”:“user2”,
“likes”:3
},
“fields”:{
“user”:[
“user2”
]
},
“sort”:[
3
]
},
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OInecmcB-IBeb8B-bF2G”,
“_score”:null,
“_source”:{
“message”:“elasticsearch is very high”,
“user”:“user1”,
“likes”:3
},
“fields”:{
“user”:[
“user1”
]
},
“sort”:[
3
]
}
]
}
}
上面的示例只返回了每个用户的第一条数据,如果需要每个用户返回2条数据呢?可以通过inner_hit来设置。
public static void search_field_collapsing() {
RestHighLevelClient client = EsClient.getClient();
try {
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(“mapping_field_collapsing_twitter”);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(
QueryBuilders.matchQuery(“message”,“elasticsearch”)
);
sourceBuilder.sort(“likes”, SortOrder.DESC);
CollapseBuilder collapseBuilder = new CollapseBuilder(“user”);
InnerHitBuilder collapseHitBuilder = new InnerHitBuilder(“collapse_inner_hit”);
collapseHitBuilder.setSize(2);
collapseBuilder.setInnerHits(collapseHitBuilder);
sourceBuilder.collapse(collapseBuilder);
searchRequest.source(sourceBuilder);
SearchResponse result = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(result);
} catch (Throwable e) {
e.printStackTrace();
} finally {
EsClient.close(client);
}
}
返回结果如下:
{
“took”:42,
“timed_out”:false,
“_shards”:{
“total”:5,
“successful”:5,
“skipped”:0,
“failed”:0
},
“hits”:{
“total”:5,
“max_score”:null,
“hits”:[
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OYnecmcB-IBeb8B-bF2X”,
“_score”:null,
“_source”:{
“message”:“to be a elasticsearch”,
“user”:“user2”,
“likes”:3
},
“fields”:{
“user”:[
“user2”
]
},
“sort”:[
3
],
“inner_hits”:{
“collapse_inner_hit”:{
“hits”:{
“total”:2,
“max_score”:0.19363807,
“hits”:[
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OonecmcB-IBeb8B-bF2q”,
“_score”:0.19363807,
“_source”:{
“message”:“to be elasticsearch”,
“user”:“user2”,
“likes”:3
}
},
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OYnecmcB-IBeb8B-bF2X”,
“_score”:0.17225473,
“_source”:{
“message”:“to be a elasticsearch”,
“user”:“user2”,
“likes”:3
}
}
]
}
}
}
},
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OInecmcB-IBeb8B-bF2G”,
“_score”:null,
“_source”:{
“message”:“elasticsearch is very high”,
“user”:“user1”,
“likes”:3
},
“fields”:{
“user”:[
“user1”
]
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!
witter",
“_type”:“_doc”,
“_id”:“OYnecmcB-IBeb8B-bF2X”,
“_score”:0.17225473,
“_source”:{
“message”:“to be a elasticsearch”,
“user”:“user2”,
“likes”:3
}
}
]
}
}
}
},
{
“_index”:“mapping_field_collapsing_twitter”,
“_type”:“_doc”,
“_id”:“OInecmcB-IBeb8B-bF2G”,
“_score”:null,
“_source”:{
“message”:“elasticsearch is very high”,
“user”:“user1”,
“likes”:3
},
“fields”:{
“user”:[
“user1”
]
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。[外链图片转存中…(img-EM8BAJOJ-1711972947555)]
[外链图片转存中…(img-Eagw76ge-1711972947556)]
[外链图片转存中…(img-tl5KqetE-1711972947556)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
总结
在这里,由于面试中MySQL问的比较多,因此也就在此以MySQL为例为大家总结分享。但是你要学习的往往不止这一点,还有一些主流框架的使用,Spring源码的学习,Mybatis源码的学习等等都是需要掌握的,我也把这些知识点都整理起来了
[外链图片转存中…(img-cQm8xFl4-1711972947556)]
[外链图片转存中…(img-6gH25v2G-1711972947556)]文章来源:https://www.toymoban.com/news/detail-849536.html
《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》,点击传送门即可获取!文章来源地址https://www.toymoban.com/news/detail-849536.html
到了这里,关于Elasticsearch Search API之(Request Body Search 查询主体)(1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!