Java實(shí)現(xiàn)Elasticsearch查詢(xún)當(dāng)前索引全部數(shù)據(jù)的完整代碼
需求背景
通常情況下,Elasticsearch 為了提高查詢(xún)效率,對(duì)于不指定分頁(yè)查詢(xún)條數(shù)的查詢(xún)語(yǔ)句,默認(rèn)會(huì)返回10條數(shù)據(jù)。那么這就會(huì)有一種情況,當(dāng)你需要一次性返回 Elasticsearch 索引中的全部數(shù)據(jù)時(shí),就無(wú)法實(shí)現(xiàn)了。這個(gè)時(shí)候你可能會(huì)考慮,比如我將每頁(yè)取值的size 設(shè)置的很大,這樣或許可以解決問(wèn)題,但是數(shù)據(jù)量的上升你是無(wú)法控制的,最終會(huì)有一天數(shù)據(jù)量會(huì)超過(guò)你此時(shí)設(shè)置的最大 size,那么這就是一個(gè)雷點(diǎn)。并且如果一次查詢(xún)很大量數(shù)據(jù)的話(huà),即便是 Elasticsearch 查詢(xún)效率高的索引結(jié)構(gòu)可能也會(huì)導(dǎo)致查詢(xún)時(shí)長(zhǎng)較長(zhǎng),甚至響應(yīng)超時(shí)。那么是否有一種查詢(xún)效率高,且相對(duì)靈活的方式可以查詢(xún) Elasticsearch 的索引中全部數(shù)據(jù)呢?答案是:有的。
通常情況
下面來(lái)看一下在不設(shè)置 size 大小的情況下,執(zhí)行 Elasticsearch 查詢(xún)語(yǔ)句默認(rèn)返回幾條數(shù)據(jù),結(jié)果是默認(rèn)返回 10條。執(zhí)行如下查詢(xún)命令
GET crm_meiqia_conversation/_search
返回結(jié)果如圖,這時(shí)我們看到返回了 10 條數(shù)據(jù)

此時(shí)如果你需要查詢(xún)更多數(shù)據(jù)的話(huà),你就可以通過(guò)指定 size 大小來(lái)查詢(xún)更多數(shù)據(jù),比如執(zhí)行如下命令
GET crm_meiqia_conversation/_search
{
"size":20
}
執(zhí)行查詢(xún)語(yǔ)句后返回的結(jié)果如圖所示,索引查詢(xún)會(huì)返回你指定 size 大小的數(shù)據(jù)

很明顯,在一些特殊的場(chǎng)景下,想要一次性查詢(xún)指定條件下的所有數(shù)據(jù)改如何操作呢,下面就來(lái)基于 Java 實(shí)現(xiàn)查詢(xún)指定條件下的所有數(shù)據(jù)操作。
Java 實(shí)現(xiàn)查詢(xún) Elasticsearch 全部數(shù)據(jù)
在具體講解如何通過(guò) Java 實(shí)現(xiàn)查詢(xún) Elasticsearch 全部數(shù)據(jù)之前,我們可以先來(lái)看一下我已經(jīng)實(shí)現(xiàn)之后的查詢(xún)效果。這里你可以看到滾動(dòng)州已經(jīng)變得很小,這就是因?yàn)槲也樵?xún)出了指定條件下的全部數(shù)據(jù)導(dǎo)致的,而不是默認(rèn)的 10 條數(shù)據(jù)

而如果沒(méi)有實(shí)現(xiàn)查詢(xún)指定索引指定條件下的全部數(shù)據(jù)時(shí),看到的效果應(yīng)該是這樣的,默認(rèn)只能一次性查詢(xún) 10 條數(shù)據(jù)返回

下面再來(lái)講一下如何通過(guò) Java 實(shí)現(xiàn) 查詢(xún) es 全部數(shù)據(jù),我們由淺入深來(lái)講解,首先來(lái)看一下默認(rèn)查詢(xún) es 10條數(shù)據(jù)的代碼,Java 通過(guò)如下 SearchRequestBuilder searchRequest = client.prepareSearch(indexProperties.getMeiqiaConversationIndex()).setTypes(indexProperties.getMeiqiaConversationType()).setQuery(query); 構(gòu)造查詢(xún) es 索引代碼,這種情況沒(méi)有設(shè)置 size 大小,默認(rèn)的話(huà)就是查詢(xún)指定索引下 10條數(shù)據(jù),完整代碼如下:
public AjaxResult getMeiqiaUidList(MeiqiaConversation meiqiaConversation) {
BoolQueryBuilder query = QueryBuilders.boolQuery();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//會(huì)話(huà)id
Long convId = meiqiaConversation.getConvId();
if (convId != null) {
boolQuery.filter(QueryBuilders.termQuery("convId",convId));
}
//會(huì)話(huà)日期
String convStartDate = (String) meiqiaConversation.getParams().get("convStartDate");
String convEndDate = (String) meiqiaConversation.getParams().get("convEndDate");
if (StringUtils.isNotEmpty(convStartDate)) {
Date date = DateUtils.stringToDate(convStartDate, DateUtils.SDF_YMDHMS);
boolQuery.filter(QueryBuilders.rangeQuery("convStartDate").gte(date.getTime()));
}
if (StringUtil.isNotEmptyString(convEndDate)) {
Date date = DateUtils.stringToDate(convEndDate, DateUtils.SDF_YMDHMS);
boolQuery.filter(QueryBuilders.rangeQuery("convEndDate").lte(date.getTime()));
}
//會(huì)話(huà)日期
Date convStartDate2 = meiqiaConversation.getConvStartDate();
Date convEndDate2 = meiqiaConversation.getConvEndDate();
if (Objects.nonNull(convStartDate2)) {
boolQuery.filter(QueryBuilders.rangeQuery("convStartDate").gte(convStartDate2.getTime()));
}
if (Objects.nonNull(convEndDate2)) {
boolQuery.filter(QueryBuilders.rangeQuery("convEndDate").lte(convEndDate2.getTime()));
}
//學(xué)號(hào)
String uid = (String) meiqiaConversation.getParams().get("uid");
if (StringUtils.isNotEmpty(uid)) {
if (uid.contains("#")) {
String replace = uid.replace("#", "");
boolQuery.filter(QueryBuilders.termQuery("clientInfo.name",replace));
}else {
boolQuery.filter(QueryBuilders.termQuery("clientInfo.uid",uid));
}
}
//客服工號(hào)
String agentId = (String) meiqiaConversation.getParams().get("agentId");
if (StringUtils.isNotEmpty(agentId)) {
boolQuery.filter(QueryBuilders.termQuery("agentId",agentId));
}
// 會(huì)話(huà)內(nèi)容
String content = (String) meiqiaConversation.getParams().get("content");
if (StringUtils.isNotEmpty(content)) {
boolQuery.filter(QueryBuilders.matchPhrasePrefixQuery("convContent.content",content));
}
query.must(boolQuery);
// 初始化搜索請(qǐng)求構(gòu)建器,用于構(gòu)造搜索請(qǐng)求
SearchRequestBuilder searchRequest = client.prepareSearch(indexProperties.getMeiqiaConversationIndex())
// 設(shè)置搜索的類(lèi)型
.setTypes(indexProperties.getMeiqiaConversationType())
// 設(shè)置查詢(xún)條件
.setQuery(query);
// 使用SearchRequest獲取搜索響應(yīng)
SearchResponse searchResponse = searchRequest.get();
// 初始化存儲(chǔ)所有搜索結(jié)果的列表
List<EsMeiqiaConversation> rows = new ArrayList<>();
// 格式化搜索響應(yīng)中的數(shù)據(jù),并添加到rows列表中
List<EsMeiqiaConversation> list1 = formatMeiqiaDto(searchResponse);
rows.addAll(list1);
//記錄返回的uid name
List<MeiqiaConversation> list = new ArrayList<>();
if (CollectionUtils.isNotEmpty(rows)) {
//獲取 uid name
Map<String, List<EsMeiqiaConversation>> collect = rows.stream().collect(Collectors.groupingBy(EsMeiqiaConversation::getClientUid, Collectors.toList()));
Set<String> uids = collect.keySet();
for (String u : uids) {
MeiqiaConversation conv = new MeiqiaConversation();
conv.setUid(u);
//同一個(gè)uid 對(duì)應(yīng)同一個(gè) name
List<EsMeiqiaConversation> esconv = collect.get(u);
String name = esconv.get(0).getClientName();
conv.setName(name);
list.add(conv);
}
}
return AjaxResult.success(list);
}
那么如何實(shí)現(xiàn) 一次查詢(xún)滿(mǎn)足條件的全部 es 數(shù)據(jù)呢,這就需要通過(guò) scroll 實(shí)現(xiàn),在初始化索引查詢(xún)構(gòu)造器時(shí)通過(guò) SearchRequestBuilder searchRequest = client.prepareSearch(indexProperties.getMeiqiaConversationIndex()).setTypes(indexProperties.getMeiqiaConversationType()).setQuery(query).setSize(100).setScroll(TimeValue.timeValueMinutes(1)); 設(shè)置 scroll 參數(shù)來(lái)實(shí)現(xiàn),同時(shí)需要再后續(xù)增加再次查詢(xún)索引邏輯,將 scorllId 循環(huán)傳遞 獲取全部數(shù)據(jù),最終改造后的獲取全部數(shù)據(jù)的代碼如下
public AjaxResult getMeiqiaUidList(MeiqiaConversation meiqiaConversation) {
BoolQueryBuilder query = QueryBuilders.boolQuery();
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
//會(huì)話(huà)id
Long convId = meiqiaConversation.getConvId();
if (convId != null) {
boolQuery.filter(QueryBuilders.termQuery("convId",convId));
}
//會(huì)話(huà)日期
String convStartDate = (String) meiqiaConversation.getParams().get("convStartDate");
String convEndDate = (String) meiqiaConversation.getParams().get("convEndDate");
if (StringUtils.isNotEmpty(convStartDate)) {
Date date = DateUtils.stringToDate(convStartDate, DateUtils.SDF_YMDHMS);
boolQuery.filter(QueryBuilders.rangeQuery("convStartDate").gte(date.getTime()));
}
if (StringUtil.isNotEmptyString(convEndDate)) {
Date date = DateUtils.stringToDate(convEndDate, DateUtils.SDF_YMDHMS);
boolQuery.filter(QueryBuilders.rangeQuery("convEndDate").lte(date.getTime()));
}
//會(huì)話(huà)日期
Date convStartDate2 = meiqiaConversation.getConvStartDate();
Date convEndDate2 = meiqiaConversation.getConvEndDate();
if (Objects.nonNull(convStartDate2)) {
boolQuery.filter(QueryBuilders.rangeQuery("convStartDate").gte(convStartDate2.getTime()));
}
if (Objects.nonNull(convEndDate2)) {
boolQuery.filter(QueryBuilders.rangeQuery("convEndDate").lte(convEndDate2.getTime()));
}
//學(xué)號(hào)
String uid = (String) meiqiaConversation.getParams().get("uid");
if (StringUtils.isNotEmpty(uid)) {
if (uid.contains("#")) {
String replace = uid.replace("#", "");
boolQuery.filter(QueryBuilders.termQuery("clientInfo.name",replace));
}else {
boolQuery.filter(QueryBuilders.termQuery("clientInfo.uid",uid));
}
}
//客服工號(hào)
String agentId = (String) meiqiaConversation.getParams().get("agentId");
if (StringUtils.isNotEmpty(agentId)) {
boolQuery.filter(QueryBuilders.termQuery("agentId",agentId));
}
// 會(huì)話(huà)內(nèi)容
String content = (String) meiqiaConversation.getParams().get("content");
if (StringUtils.isNotEmpty(content)) {
boolQuery.filter(QueryBuilders.matchPhrasePrefixQuery("convContent.content",content));
}
query.must(boolQuery);
// 初始化搜索請(qǐng)求構(gòu)建器,用于構(gòu)造搜索請(qǐng)求
SearchRequestBuilder searchRequest = client.prepareSearch(indexProperties.getMeiqiaConversationIndex())
// 設(shè)置搜索的類(lèi)型
.setTypes(indexProperties.getMeiqiaConversationType())
// 設(shè)置查詢(xún)條件
.setQuery(query)
// 設(shè)置返回結(jié)果的數(shù)量為100
.setSize(100)
// 設(shè)置滾動(dòng)查詢(xún)的時(shí)間間隔為1分鐘
.setScroll(TimeValue.timeValueMinutes(1));
// 使用SearchRequest獲取搜索響應(yīng)
SearchResponse searchResponse = searchRequest.get();
// 初始化存儲(chǔ)所有搜索結(jié)果的列表
List<EsMeiqiaConversation> rows = new ArrayList<>();
// 格式化搜索響應(yīng)中的數(shù)據(jù),并添加到rows列表中
List<EsMeiqiaConversation> list1 = formatMeiqiaDto(searchResponse);
rows.addAll(list1);
// 使用Scroll方式遍歷所有搜索結(jié)果
do {
// 準(zhǔn)備下一次Scroll搜索,設(shè)置滾動(dòng)時(shí)間為1分鐘
// 將scorllId循環(huán)傳遞 獲取全部數(shù)據(jù)
searchResponse = client.prepareSearchScroll(searchResponse.getScrollId()).setScroll(TimeValue.timeValueMinutes(1)).execute().actionGet();
// 格式化新一批搜索結(jié)果,并添加到rows列表中
List<EsMeiqiaConversation> list = formatMeiqiaDto(searchResponse);
if (CollectionUtils.isNotEmpty(list)) {
rows.addAll(list);
}
// 當(dāng)搜索結(jié)果為空時(shí),結(jié)束循環(huán)
// 當(dāng)searchHits的數(shù)組為空的時(shí)候結(jié)束循環(huán),至此數(shù)據(jù)全部讀取完畢
} while (searchResponse.getHits().getHits().length != 0);
// 創(chuàng)建一個(gè)ClearScrollRequest實(shí)例,用于清除滾動(dòng)查詢(xún)的會(huì)話(huà)。
ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
// 將上一次查詢(xún)返回的滾動(dòng)ID添加到請(qǐng)求中,以便清除這個(gè)特定的會(huì)話(huà)。
// 這是必要的,因?yàn)镃learScrollRequest需要至少一個(gè)滾動(dòng)ID才能執(zhí)行清除操作。
clearScrollRequest.addScrollId(searchResponse.getScrollId());
// 發(fā)送ClearScroll請(qǐng)求并獲取操作的結(jié)果。
// 這一步是必需的,因?yàn)樗鼘?shí)際執(zhí)行了清除滾動(dòng)會(huì)話(huà)的操作,并允許我們處理結(jié)果或任何異常。
client.clearScroll(clearScrollRequest).actionGet();
//記錄返回的uid name
List<MeiqiaConversation> list = new ArrayList<>();
if (CollectionUtils.isNotEmpty(rows)) {
//獲取 uid name
Map<String, List<EsMeiqiaConversation>> collect = rows.stream().collect(Collectors.groupingBy(EsMeiqiaConversation::getClientUid, Collectors.toList()));
Set<String> uids = collect.keySet();
for (String u : uids) {
MeiqiaConversation conv = new MeiqiaConversation();
conv.setUid(u);
//同一個(gè)uid 對(duì)應(yīng)同一個(gè) name
List<EsMeiqiaConversation> esconv = collect.get(u);
String name = esconv.get(0).getClientName();
conv.setName(name);
list.add(conv);
}
}
return AjaxResult.success(list);
}
那么這段的核心代碼是增加了滾動(dòng)查詢(xún)數(shù)據(jù)的操作,如圖所示

同時(shí)再執(zhí)行循環(huán)查詢(xún)時(shí)將 scrollId 循環(huán)傳遞,并將查詢(xún)結(jié)果 addAll 到當(dāng)前l(fā)ist 的集合中

查詢(xún)結(jié)束之后,最后是清除滾動(dòng)會(huì)話(huà)的操作

到這里關(guān)于 Java 實(shí)現(xiàn) es 查詢(xún)指定條件下的全部數(shù)據(jù)操作就結(jié)束了,整個(gè)操作過(guò)程比較容易理解,增加了 es 滾動(dòng)查詢(xún) scroll 操作來(lái)實(shí)現(xiàn)查詢(xún) es 全部數(shù)據(jù)。
寫(xiě)在最后
最后想要說(shuō)的是,對(duì)于 es 查詢(xún),通常情況下是不需要一次性查詢(xún)出當(dāng)前索引所有條件下的數(shù)據(jù)的,畢竟數(shù)據(jù)量比較大,但是也有特殊的場(chǎng)景,這個(gè)時(shí)候不得不一次性查詢(xún)出所有的數(shù)據(jù),這就需要上文中用到的辦法了,希望對(duì)大家有幫助。
到此這篇關(guān)于Java實(shí)現(xiàn)Elasticsearch查詢(xún)當(dāng)前索引全部數(shù)據(jù)的文章就介紹到這了,更多相關(guān)Java Elasticsearch查詢(xún)當(dāng)前索引全部數(shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用Jenv管理多版本JDK環(huán)境的詳細(xì)教程
在現(xiàn)代 Java 開(kāi)發(fā)中,我們經(jīng)常需要在不同的項(xiàng)目中使用不同版本的 JDK,手動(dòng)切換 JAVA_HOME 環(huán)境變量既繁瑣又容易出錯(cuò),Jenv 是一個(gè)優(yōu)秀的 JDK 版本管理工具,可以讓我們輕松地在不同 JDK 版本間切換,所以本文給大家介紹了使用Jenv管理多版本JDK環(huán)境的詳細(xì)教程2025-08-08
從零開(kāi)始讓你的Spring?Boot項(xiàng)目跑在Linux服務(wù)器
這篇文章主要給大家介紹了如何從零開(kāi)始讓你的Spring?Boot項(xiàng)目跑在Linux服務(wù)器的相關(guān)資料,由于springboot是內(nèi)嵌了tomcat,所以可以直接將項(xiàng)目打包上傳至服務(wù)器上,需要的朋友可以參考下2021-11-11
java ConcurrentHashMap分段加鎖提高并發(fā)效率
這篇文章主要為大家介紹了java ConcurrentHashMap分段加鎖提高并發(fā)效率,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
Java的stream流多個(gè)字段排序的實(shí)現(xiàn)
本文主要介紹了Java的stream流多個(gè)字段排序的實(shí)現(xiàn),主要是兩種方法,第一種是固定多個(gè)字段排序和第二種動(dòng)態(tài)字段進(jìn)行排序,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10
Java?熱更新?Groovy?實(shí)踐及踩坑指南(推薦)
Apache的Groovy是Java平臺(tái)上設(shè)計(jì)的面向?qū)ο缶幊陶Z(yǔ)言,這門(mén)動(dòng)態(tài)語(yǔ)言擁有類(lèi)似Python、Ruby和Smalltalk中的一些特性,可以作為Java平臺(tái)的腳本語(yǔ)言使用,這篇文章主要介紹了Java?熱更新?Groovy?實(shí)踐及踩坑指南,需要的朋友可以參考下2022-09-09
IntelliJ IDEA 關(guān)閉多余項(xiàng)目的操作方法
這篇文章主要介紹了IntelliJ IDEA 關(guān)閉多余項(xiàng)目的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
基于Mybatis實(shí)現(xiàn)CRUD操作過(guò)程解析(xml方式)
這篇文章主要介紹了基于Mybatis實(shí)現(xiàn)CRUD操作過(guò)程解析(xml方式),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11

