您的位置:首页 > 其它

ElasticSearch如何一次查询出全部数据

2018-08-30 13:15 573 查看

使用from size进行分页查询(深度分页),当数据量大的时候,对全部数据进行遍历,使用from size性能会很差。from指的是从哪里开始拿数据,size是结果集中返回的文档个数。from-size的工作原理是:如size=10&from=100,那么Elasticsearch会从每个分片里取出110条数据,然后汇集到一起再排序,取出101~110序号的文档。由此可见,from-size的效率必然不会很高,特别是分页越深,需要排序的数据越多,其效率就越低。

Elasticsearch中进行大数据量查询时,往往因为设备、网络传输问题影响查询数据的效率;Elasticsearch中提供了Scroll(游标)的方式对数据进行少量多批次的滚动查询,来提高查询效率。

/**
* 查询所有数据
*
* @param index 索引名称
* @param type type 6.0后不推荐使用
* @param fields 需要显示的字段
* @param sortField 需要进行排序的字段
* @param highlightField 需要高亮的字段
* @param queryBuilder 查询条件
* @return
*/
public static List<Map<String, Object>> searchAllData(String index, String type, String fields, String sortField, String highlightField,QueryBuilder queryBuilder ) {
//指定一个index和type
SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index).setTypes(type);
// 高亮(xxx=111,aaa=222)
if (StringUtils.isNotEmpty(highlightField)) {
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<span style='color:red;font-weight:bold'>");//设置前缀
highlightBuilder.postTags("</span>");//设置后缀
// 设置高亮字段
highlightBuilder.field(highlightField);
searchRequestBuilder.highlighter(highlightBuilder);
}
// 需要显示的字段,逗号分隔(缺省为全部字段)
if (StringUtils.isNotEmpty(fields)) {
searchRequestBuilder.setFetchSource(fields.split(","), null);
}
searchRequestBuilder.setFetchSource(true);
if (StringUtils.isNotEmpty(sortField)) {
searchRequestBuilder.addSort(sortField, SortOrder.ASC);
}
//设置每批读取的数据量
searchRequestBuilder.setSize(100);
//查询条件
searchRequestBuilder.setQuery(queryBuilder);
//设置 search context 维护1分钟的有效期
searchRequestBuilder.setScroll(TimeValue.timeValueMinutes(1));
//获得首次的查询结果
SearchResponse scrollResp=searchRequestBuilder.get();
//打印的内容 可以在 Elasticsearch head 和 Kibana  上执行查询
LOGGER.info("\n{}", searchRequestBuilder);
//打印命中数量
LOGGER.info("命中总数量:{}", scrollResp.getHits().getTotalHits());
List<Map<String, Object>> sourceList = new ArrayList<Map<String, Object>>();
StringBuffer stringBuffer = new StringBuffer();
do {
//将scorllId循环传递
scrollResp = client.prepareSearchScroll(scrollResp.getScrollId()).setScroll(TimeValue.timeValueMinutes(1)).execute().actionGet();
for (SearchHit searchHit : scrollResp.getHits().getHits()) {
searchHit.getSourceAsMap().put("id", searchHit.getId());
if (StringUtils.isNotEmpty(highlightField)) {
if (!ObjectUtils.isEmpty(searchHit.getHighlightFields().get(highlightField))) {
Text[] text = searchHit.getHighlightFields().get(highlightField).getFragments();
if (text != null) {
for (Text str : text) {
stringBuffer.append(str.string());
}
//遍历 高亮结果集,覆盖 正常结果集
searchHit.getSourceAsMap().put(highlightField, stringBuffer.toString());
}
}
}
sourceList.add(searchHit.getSourceAsMap());
}
//当searchHits的数组为空的时候结束循环,至此数据全部读取完毕
} while(scrollResp.getHits().getHits().length != 0);
//删除scroll
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
clearScrollRequest.addScrollId(scrollResp.getScrollId());
client.clearScroll(clearScrollRequest).actionGet();
return sourceList;

}
阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: