上篇ES系列一之java端API操作結束後本以為就相安無事了,但生產的問題是層出不窮的;下面我就再記錄下近幾周遇到的問題以及解決方案;
一 更新ES資訊報錯
報錯資訊如下:
Use ElasticsearchException.getFailedDocuments() for detailed messages [{yjZ8D0oB=ElasticsearchException[Elasticsearch exception [type=cluster_block_exception, reason=index [au_report] blocked by: [FORBIDDEN/12/index read-only / allow delete (api)];]]
分析:看報錯資訊大概意思就是es的寫入操作被阻塞了,索引只能讀、刪不能修改新增了;我總結了這種錯誤的解決方案以及步驟,如下:
- 1、傳送請求將read_only_allow_delete屬性置成false或者刪除;如下:
curl --location --request PUT 'http://127.0.0.1:9200/au_report/_settings' \
--header 'Content-Type: application/json' \
--data-raw '{
"index.blocks.read_only_allow_delete": null
}'
read_only_allow_delete表示es只讀和允許刪除不能做修改操作,當磁碟空間達到95%時自動為true;
- 2、如果上述請求成功後仍然報錯,那麼可以檢視es使用磁碟的空間佔用情況,呼叫如下:
curl --location --request GET 'http://127.0.0.1:9200/_cat/allocation?v'
下面貼上該請求返回的各項代表的意思:- shards:分片數
- disk.indices:索引index佔用的空間大小
- disk.used:已用磁碟空間
- disk.avail:可用磁碟空間
- disk.total:磁碟空間總量
- disk.percent:磁碟已使用百分比
- host:節點主機地址
- ip:節點ip
- node:節點名稱
- 3、我的情況就是這裡發現disk.percent磁碟已使用空間的百分比已經超過98%了,所以我的當務之急是改配置或者刪資料;由於我這邊的es服務並非自己搭建的,於是登入es主機進行了以下操作
- 透過jps或者ps -ef | grep elastic檢視es的程式ID
- 透過ll /proc/程式ID/cwd 檢視es安裝位置
- 透過檢視es的配置檔案/elasticsearch-7.6.2/config/elasticsearch.yml的配置發現並未配置es檔案的落盤位置,那麼預設應該是與當前安裝目錄在同一個磁碟;
- 於是透過df -h [指定目錄] 檢視es安裝目錄磁碟佔用情況,發現果然超過95%了,其實上面透過/_cat/allocation?v請求已經知悉磁碟空間使用情況了,這裡只是做一個校驗確定
- 4、由於磁碟空間我這邊無法清理,於是找運維同事在有足夠磁碟空間的目錄下建立data和log資料夾,然後將elasticsearch.yml裡的path.data和path.log的值換成新建的data和log目錄,然後重啟就解決了這個報錯
二、命中結果高亮展示
我使用的spring-data-elasticsearch的版本是4.3.4,其實只要在ES系列一之java端API操作;分頁查詢的測試方法queryPageData()基礎上新增HighlightBuilder
設定需要高亮的欄位然後設定到返回結果去即可,下面貼上查詢程式碼:
@Test
public void queryPageData(){
// 此處應是查詢引數,這裡單元測試沒有賦值
TestQuery query = new TestQuery();
query.setTextKey("張三");
PaginationModel<EsTestInfo> res = new PaginationModel<>();
int currentPage=query.getPageIndex()-1;
int pageSize = query.getPageSize();
PageRequest pageRequest = PageRequest.of(currentPage, pageSize);
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
BoolQueryBuilder textKeyBqb = new BoolQueryBuilder();
if (StringUtils.isNotBlank(query.getTextKey())) {
/**
* 由於下面會用到must查詢,所以此處用textKeyBqb再封裝一個builder出來,否則
* 和must同時查詢此處會出現0匹配也返回結果的情況
* 如果不想封裝textKeyBqb,加上boolQueryBuilder.minimumShouldMatch(1)強制使es
* 最少滿足一個should子句才能返回結果也行
*/
textKeyBqb.should(QueryBuilders.matchQuery("id", query.getTextKey()))
.should(QueryBuilders.matchQuery("name", query.getTextKey()))
.should(QueryBuilders.matchQuery("desc", query.getTextKey()));
}
if (Objects.nonNull(query.getStartDate()) && Objects.nonNull(query.getEndDate())) {
RangeQueryBuilder timeRangeQuery = QueryBuilders.rangeQuery("publishDt")
.gte(query.getStartDate().getTime())
.lte(query.getEndDate().getTime());
boolQueryBuilder.must(timeRangeQuery);
}
if (Objects.nonNull(query.getRptStatus())) {
boolQueryBuilder.must(QueryBuilders.matchQuery("rptStatus", query.getRptStatus()));
}
// 將上面封裝的子句加入到主查詢條件中
boolQueryBuilder.must(textKeyBqb);
log.info("<<<<<<<<<<<<<<<<<<boolQueryBuilder:{}",boolQueryBuilder);
NativeSearchQuery searchQuery = new NativeSearchQueryBuilder()
.withQuery(boolQueryBuilder).withPageable(pageRequest)
// 設定需要高亮的欄位
.withHighlightFields(
new HighlightBuilder.Field("name")
,new HighlightBuilder.Field("desc"))
// 設定高亮的html格式
.withHighlightBuilder(new HighlightBuilder().preTags("<span style='color:red'>").postTags("</span>")).build();
// 解決es一次只返回10000條資料的問題
searchQuery.setTrackTotalHits(true);
SearchHits<EsTestInfo> search = elasticsearchRestTemplate.search(searchQuery, EsTestInfo.class);
List<EsTestInfo> list = new ArrayList<>();
for (SearchHit<EsTestInfo> productSearchHit : search) {
EsTestInfo pro = productSearchHit.getContent();
//獲取高亮的欄位集合
Map<String, List<String>> highlightFields = productSearchHit.getHighlightFields();
//將高亮的內容填充到pro中
pro.setName(highlightFields.get("name")==null ? pro.getName():highlightFields.get("name").get(0));
pro.setDesc(highlightFields.get("desc")==null ? pro.getDesc():highlightFields.get("desc").get(0));
System.out.println("pro = " + pro);
list.add(pro);
}
res.setList(list);
res.setTotal(search.getTotalHits());
res.setPageIndex(query.getPageIndex());
res.setPageSize(query.getPageSize());
System.out.println("res = " + res);
}
測試結果如下:
這次更新的問題到此結束,後續遇到新的問題會繼續補充......