我之前做了一个 ES 刷数的工具类,经常需要对 ES 中满足某些条件的数据进行一些操作,可以看到模板方法中互异的查询条件 bqb 可以通过参数传入,而根据查询结构封装更新逻辑则需要将方法作为参数传入。
这里的核心就是将方法作为参数,从而使得不同的方法之间既可以复用逻辑又可以有不同的逻辑。这里自然就想到了 JDK8 的函数式接口和 lambda 表达式,而 JDK 自身提供的 Function 函数式接口就很符合这个场景, Function 就是一个函数,其作用类似于数学中函数的定义 y = f(x),另外还可以使用 Function 函数式接口的 compose 和 andThen 实现更复杂的逻辑控制。
//模板方法 privatevoidupdateByScroll(BoolQueryBuilder bqb, Function<SearchHit[], List<EsCommentModel>> function){ LOGGER.info(">>>>>>>>>>>>> updateByScroll method begin >>>>>>>>>>>> "); Date begin = new Date(); Integer sum = 0; SearchResponse scrollResp = transportClient.prepareSearch(aliasSearch).setTypes(TYPE) .setQuery(bqb) .setScroll(new TimeValue(60000)) .setSize(100).get(); //max of 100 hits will be returned for each scroll //Scroll until no hits are returned do { sum += scrollResp.getHits().getHits().length; List<EsCommentModel> comments = function.apply(scrollResp.getHits().getHits()); try { ESUtil.bulkUpdate(comments, false); } catch (SearchExecuteException e) { LOGGER.error("bulkUpdate ex", e); } scrollResp = transportClient.prepareSearchScroll(scrollResp.getScrollId()).setScroll(new TimeValue(60000)).execute().actionGet(); } while(scrollResp.getHits().getHits().length != 0); // Zero hits mark the end of the scroll and the while loop. Date end = new Date(); LOGGER.info(">>>>>>>>>>>>> updateByScroll method end >>>>>>>>>>>> "); LOGGER.info(">>>>>>>>>>>>> updateByScroll method update sum: {} >>>>>>>>>>>>", sum); LOGGER.info(">>>>>>>>>>>>> updateByScroll method costs: {} >>>>>>>>>>>>", end.getTime() - begin.getTime()); }
//具体方法实现1 publicvoidupdateSellerAccount(){ BoolQueryBuilder bqb = QueryBuilders.boolQuery().filter(termQuery("seller_account", "arnontakorn1")); LOGGER.info("updateSellerAccount bqb = {}", bqb.toString()); updateByScroll(bqb, hits -> { List<EsCommentModel> comments = new ArrayList<EsCommentModel>(hits.length); for (SearchHit hit : hits) { String id = hit.getId(); EsCommentModel model = new EsCommentModel(); model.setCommentId(Long.valueOf(id)); model.setSellerAccount("arnontakorn"); comments.add(model); } return comments; }); }