ES系列二之常見問題解決

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

測試結果如下:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章