查询 API
Search API 可以执行一个查询操作,返回与查询条件相匹配的结果。
允许跨index查询,也可以跨type查询。
可以使用 query 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")
.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();
注意:尽管JavaAPI定义了额外的搜索类型 QUERY_AND_FETCH 和 DFS_QUERY_AND_FETCH , 但这些模式其实是底层自动优化时使用的模式,不应该由用户通过API指定。 |
有关索引操作的更多信息,请查看 REST search。
使用分页
首先请阅读 scroll documentation
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(); (1)
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); (2)
1 | 每次查询最多返回100条结果 |
2 | 没有结果返回的时候就停止循环和游标 |
多条件查询
查看 MultiSearch API Query 文档
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();
long nbHits = 0;
for (MultiSearchResponse.Item item : sr.getResponses()) { (1)
SearchResponse response = item.getResponse();
nbHits += response.getHits().getTotalHits();
}
1 | 可以从 MultiSearchResponse#getResponses() 中获取所有独立的响应 |
使用聚合
下面这段代码展示了如何在一次查询中加入两个聚合:
SearchResponse sr = client.prepareSearch()
.setQuery(QueryBuilders.matchAllQuery())
.addAggregation(
AggregationBuilders.terms("agg1").field("field")
)
.addAggregation(
AggregationBuilders.dateHistogram("agg2")
.field("birth")
.dateHistogramInterval(DateHistogramInterval.YEAR)
)
.get();
Terms agg1 = sr.getAggregations().get("agg1"); (1)
Histogram agg2 = sr.getAggregations().get("agg2");
1 | 获取某部分结果 |
详情请查看 Aggregations Java API 。
提前结束查询
设置一次查询的最大数,到达这个数量的时候,查询操作就会提前终止。
如果设置了的话,可以在 SearchResponse
对象中使用 isTerminatedEarly()
查看操作是否提前结束。例:
SearchResponse sr = client.prepareSearch(INDEX)
.setTerminateAfter(1000) (1)
.get();
if (sr.isTerminatedEarly()) {
// 提前结束时的逻辑
}
1 | 查询到1000个文档就停止 |
搜索模板
查看 Search Template 文档
将模版参数定义成 Map<String,Object>
类型:
Map<String, Object> template_params = new HashMap<>();
template_params.put("param_gender", "male");
可以将模版存储在 config/scripts
目录下。
如果你的脚本在 config/scripts/template_gender.mustache
,则可以这样查询:
{
"query" : {
"match" : {
"gender" : "{{param_gender}}"
}
}
}
创建你的查询请求模版:
SearchResponse sr = new SearchTemplateRequestBuilder(client)
.setScript("template_gender") (1)
.setScriptType(ScriptService.ScriptType.FILE) (2)
.setScriptParams(template_params) (3)
.setRequest(new SearchRequest()) (4)
.get() (5)
.getResponse(); (6)
1 | 模版名 |
2 | 模版存储在本地硬盘 gender_template.mustache |
3 | 模版参数 |
4 | 设置执行上下文(可以在这里定义index名称) |
5 | 执行并获取模版的响应 |
6 | 从模板响应中获取查询结果 |
你也可以将模版存储在集群state中:
client.admin().cluster().preparePutStoredScript()
.setScriptLang("mustache")
.setId("template_gender")
.setSource(new BytesArray(
"{\n" +
" \"query\" : {\n" +
" \"match\" : {\n" +
" \"gender\" : \"{{param_gender}}\"\n" +
" }\n" +
" }\n" +
"}")).get();
要执行该模版,需要使用 ScriptService.ScriptType.STORED
类型:
SearchResponse sr = new SearchTemplateRequestBuilder(client)
.setScript("template_gender") (1)
.setScriptType(ScriptType.STORED) (2)
.setScriptParams(template_params) (3)
.setRequest(new SearchRequest()) (4)
.get() (5)
.getResponse(); (6)
1 | 模版名 |
2 | 模版存储在集群state中 |
3 | 模版参数 |
4 | 设置执行上下文(可以在这里定义index名称) |
5 | 执行并获取模版的响应 |
6 | 从模板响应中获取查询结果 |
你也可以执行inline(内联)模版:
sr = new SearchTemplateRequestBuilder(client)
.setScript("{\n" + (1)
" \"query\" : {\n" +
" \"match\" : {\n" +
" \"gender\" : \"{{param_gender}}\"\n" +
" }\n" +
" }\n" +
"}")
.setScriptType(ScriptType.INLINE) (2)
.setScriptParams(template_params) (3)
.setRequest(new SearchRequest()) (4)
.get() (5)
.getResponse(); (6)
1 | 模板体 |
2 | 模版是通过inline方式传递的 |
3 | 模版参数 |
4 | 设置执行上下文(可以在这里定义index名称) |
5 | 执行并获取模版的响应 |
6 | 从模板响应中获取查询结果 |