ES系列二之常見問題解決

木木他爹發表於2022-11-26

上篇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);
    }

測試結果如下:

這次更新的問題到此結束,後續遇到新的問題會繼續補充......

相關文章