繁体   English   中英

具有空索引的 Elasticsearch 和 spring 数据

[英]Elasticsearch and spring data with empty index

我有一个关于 elasticsearch with spring data 的问题。

@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "my_es_index")
public class MyEsIndex {

    private String id;

    private Long counter;

    private Long timestamp;
}

和存储库

public interface MyEsIndexRepository extends ElasticsearchRepository<MyEsIndex, String> {

    Optional<MyEsIndex> findFirstByIdOrderByTimestampDesc(String id);
}

所以我有一项服务,我必须首先搜索以前保存的记录以检索以前的值,总是按时间戳顺序进行搜索。

@Service
@RequiredArgsConstructor
public class MyEsService {

private final MyEsIndexRepository repository;

  public MyEsIndex insert(String previousId) {
    Long previousCounter = 
repository.findFirstByIdOrderByTimestampDesc(previousId).map(MyEsIndex::getCounter).orElse(0L);
    var index = new MyEsIndex(UUID.randomUUID().toString(), ++previousCounter, 
    Instant.now().toEpochMilli());
    return repository.save(index);
  }
}

并且在尝试执行接收操作时{"error":{"root_cause":[{"type":"query_shard_exception","reason":"No mapping found for [timestamp] in order to sort on","index":"my_es_index"}

是否可以在空索引上对 elasticsearch 中的字段进行初始化? 因为 init config 的解决方案不是那么清楚,因为它只会在开始使用从未保存记录的空索引时使用一次

@Configuration
public class InitElasticsearchConfig {

private final MyEsIndexRepository repository;

  @EventListener(ApplicationReadyEvent.class)
  public void initIndex() {
  if (repository.findAll(PageRequest.of(0, 1)).isEmpty()) {
    var initIndex = new MyEsIndex("initId", 0L, 0L);
    repository.save(initIndex);
    repository.delete(initIndex);
  }
}

是否可以将此解决方案委托给 spring? 我没找到

当使用 Spring Data Elasticsearch 存储库时 - 正如您所做的那样 - 正常行为是在索引尚不存在时在应用程序启动时创建索引后将映射写入 Elasticsearch。

您的代码中的问题是您没有定义实体的属性应该映射到什么类型; 你需要添加@Field注释来做到这一点:

@Document(indexName = "my_es_index")
public class MyEsIndex {

    private String id;

    @Field(type = FieldType.Long)
    private Long counter;

    @Field(type = FieldType.Long)
    private Long timestamp;
}

未使用@Field注释进行注释的属性不会写入映射,而是留给 Elasticsearch 自动映射,这就是排序不起作用的原因。 由于没有文档写入索引,Elasticsearch 不知道它是什么类型以及如何对其进行排序。

在您的代码中还有另一件事可能与您所需的应用程序逻辑不匹配。 在 Spring Data Elasticsearch 中,一个实体需要有一个id属性,该属性将在 Elasticsearch 中用作文档的 id。 这通常是通过使用@Id注释属性来定义的,如果缺少 - 就像您的情况一样 - 使用名称为“id”或“document”的属性。 因此,在您的情况下,使用了属性id

一个文档的id在Elasticsearch中是唯一的,如果你用一个已有的id存储一个新的文档,之前的内容将被覆盖。 如果那是您想要的,您应该将@Id注释添加到您的属性以明确这是唯一的 ID。 但是在这种情况下,您的代码findFirstByIdOrderByTimestamp没有意义,因为按 id 查找将始终返回最多一个文档,因此顺序无关紧要,您可以只使用findById()然后。 我假设id在您使用 UUID 初始化它时应该是唯一的。

如果您的id不是唯一的,并且您有多个具有相同 id 和不同时间戳的文档,则您需要向您的实体添加一个新的唯一属性并使用@Id对其进行注释以防止将id用作唯一标识符。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM