Java Elasticsearch8.x索引管理可複用程式碼塊

Jackie_JK發表於2024-12-07

索引列舉:

@Getter
@AllArgsConstructor
public enum ElasticsearchIndex {

  AAA("aaa", true),

  ;

  @Getter(AccessLevel.PROTECTED)
  private final String mainName;

  //是否是滾動索引
  @Getter(AccessLevel.PRIVATE)
  private final boolean rolling;

  @Setter(AccessLevel.PROTECTED)
  private static String prefix;

  private static final String SUFFIX = "-alias";

  private static final String SEQUENCE_START = "000001";

  private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

  private static final DateTimeFormatter YEAR_MONTH_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM");


  public String getAlias(LocalDate date) {
    return String.join("_", prefix, mainName, DATE_TIME_FORMATTER.format(date)) + SUFFIX;
  }

  public String getAlias(YearMonth yearMonth) {
    return String.join("_", prefix, mainName, YEAR_MONTH_DATE_TIME_FORMATTER.format(yearMonth)) + SUFFIX;
  }

  public List<String> getAliases(LocalDate date) {
    if (!rolling) {
      return getAliases();
    }
    return Collections.singletonList(String.join("_", prefix, mainName, DATE_TIME_FORMATTER.format(date)) + SUFFIX);
  }

  public List<String> getAliases() {
    if (rolling) {
      return getAliases(LocalDate.now());
    }
    return Collections.singletonList(String.join("_", prefix, mainName)+ SUFFIX);
  }

  public List<String> getAliases(LocalDate start, LocalDate end) {
    if (!rolling) {
      return getAliases();
    }
    if (start.isAfter(end)) {
      LocalDate buff = start;
      start = end;
      end = buff;
    } else if (start.equals(end)) {
      return getAliases(start);
    }
    int len = (int) ChronoUnit.DAYS.between(start, end) + 1;
    List<String> res = new ArrayList<>(len);
    for (int i = 0; i < len; i++) {
      res.add(getAlias(start));
      start = start.plusDays(1);
    }
    return res;
  }

  String getFirstIndex(LocalDate date) {
    return String.join("_", prefix, mainName, DATE_TIME_FORMATTER.format(date)) + "-" + SEQUENCE_START;
  }

}

對映獲取方法:

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class MappingUtils {

  private static final String MAPPING_PATH = File.separator + "elasticsearch_index" + File.separator;

  public static InputStream getInputStream(String fileName) throws IOException {
    fileName = fileName + ".json";
    Resource resource = new ClassPathResource(MAPPING_PATH + fileName);
    return resource.getInputStream();
  }

}

索引建立方法:

@NoArgsConstructor(access = AccessLevel.PRIVATE)
@Slf4j
public class ElasticsearchIndexUtil {

  @Setter(AccessLevel.PROTECTED)
  private static ElasticsearchClient client;

  @Setter(AccessLevel.PROTECTED)
  private static Map<String, String> lifecycle;

  /*
   * 建立索引
   * */
  public static boolean createIndex(ElasticsearchIndex index, LocalDate date, Reader mapping) throws IOException {
    String rollingIndex = index.getFirstIndex(date);
    Map<String, Alias> aliasMap = Maps.newHashMapWithExpectedSize(2);
    aliasMap.put(index.getAlias(date), Alias.of(b -> b.isWriteIndex(true)));
    aliasMap.put(index.getAlias(YearMonth.from(date)), Alias.of(b -> b.isWriteIndex(false)));
    CreateIndexRequest request = CreateIndexRequest.of(
        a -> a.index(rollingIndex).mappings(m -> m.withJson(mapping))
            .settings(setting -> setting.numberOfReplicas("1").numberOfShards("3")
                .lifecycle(lc -> lc.name(lifecycle.get(index.getMainName())).rolloverAlias(index.getAlias(date))))
            .aliases(aliasMap));
    CreateIndexResponse response;
    try {
      response = client.indices().create(request);
    } catch (ElasticsearchException e) {
      if ("resource_already_exists_exception".equals(e.response().error().type())) {
        log.info("索引已存在:{}", rollingIndex);
      } else {
        log.info("建立索引失敗:{}", rollingIndex, e);
      }
      return false;
    }
    return response.acknowledged();
  }

}

索引建立定時任務:

@Service
@DependsOn("elasticsearchClient")
public class ElasticSearchIndexGenerator {

  @PostConstruct
  public void init() throws IOException {
    generate(LocalDate.now());
  }

  @Scheduled(cron = "0 0 22 * * ?")
  @ScheduledLock(1000 * 60 * 10)
  protected void generate() throws IOException {
    generate(LocalDate.now().plusDays(1));
  }

  protected void generate(LocalDate date) throws IOException {
    try (InputStream inputStream = MappingUtils.getInputStream(ElasticsearchIndex.AAA.getMainName())) {
      InputStreamReader mapping = new InputStreamReader(inputStream);
      ElasticsearchIndexUtil.createIndex(ElasticsearchIndex.AAA, date, mapping);
    }
  }

}

相關文章