有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java Spring Data ElasticSearch 4.0.0使用通配符搜索同一类的多个索引

所以我对ElasticSearch和Spring数据都是新手,我有一个任务来存储所有发送电子邮件的html内容

@Document(indexName = "email")
@Mapping(mappingPath = "elastic/mappings/email.json")
public class EsOutboundEmail extends PartitionedDocument {

我被告知要按月编制索引,我想这是为了以后冻结旧数据,所以我想出了类似的办法

public String indexByMonth(AbstractDocument source) {
    final IndexCoordinates cos = elasticSearchMappingInitializer.getOrCreateDatedIndex(source.getClass());

    IndexQueryBuilder queryBuilder = new IndexQueryBuilder()
            .withId(source.getId())
            .withObject(source);

    return elasticsearchOperations.index(queryBuilder.build(), cos);
}

命名是这样的(忽略“初始值设定项”bean名称,这会改变):

   public IndexCoordinates getOrCreateDatedIndex(Class<? extends AbstractDocument> clazz) {
       String indexName = getIndexName(clazz);
       indexName = String.format("%s-%s", indexName, now().format(DateTimeFormatter.ofPattern("yyyy-MM")));
       final IndexOperations indexOperations = elasticsearchOperations.indexOps(IndexCoordinates.of(indexName));
       if (!indexOperations.exists()) {
           indexOperations.create();
           indexOperations.createMapping(clazz);
       }
       return IndexCoordinates.of(indexName);
   }

   public String getIndexName(Class<? extends AbstractDocument> clazz) {
       if (!clazz.isAnnotationPresent(Document.class)) {
           throw new IllegalStateException("Elasticsearch domain must have @Document annotation!");
       }

       Document annotation = clazz.getDeclaredAnnotation(Document.class);
       return annotation.indexName();
   }

因此结果将是email-2020-06

现在,在这里搜索感觉有点不舒服:

    public <T extends AbstractDocument> T searchOneDated(Query query, Class<T> clazz) {
        String indexName = elasticSearchMappingInitializer.getIndexName(clazz);
        indexName = format("%s-*", indexName);

        return ofNullable(elasticsearchOperations.searchOne(query, clazz, IndexCoordinates.of(indexName)))
                .map(SearchHit::getContent)
                .orElse(null);
    }

我无法摆脱一种感觉,即有一种方法可以用更简单的方式来实现这一点,但正如我所说,我是一个新手,4.0.0的参考文档对这个案例没有帮助,因此我非常感谢了解这一点的人提供的任何意见。提前谢谢


共 (1) 个答案

  1. # 1 楼答案

    您可以在@Document注释中使用SpEL表达式,例如:

    @Document(indexName="email-#{T(java.time.LocalDate).now().format(T(java.time.format.DateTimeFormatter).ofPattern(\"yyyy-MM\"))}")
    public class EsOutboundEmail extends PartitionedDocument {
      // ...
    }
    

    要保存实体,请执行以下操作:

    ESOutboundEmail email = ...;
    elasticsearchOperations.save(email);
    

    以及查询:

    elasticsearchOperations.searchOne(query, clazz)
    

    如果索引不存在,您仍然需要确保已创建索引(请注意,我添加了对putMapping(Document)的调用,但您忽略了这一点):

       final IndexOperations indexOperations = elasticsearchOperations.indexOps(EsOutboundEmail.class);
       if (!indexOperations.exists()) {
           indexOperations.create();
           Document mapping = indexOperations.createMapping(clazz);
           indexOperations.putMapping(mapping);
       }
    

    编辑2020-06-16:

    我在搜索中漏掉了通配符:

    elasticsearchOperations.searchOne(query, clazz, IndexCoordinates.of("email-*"))