我们可以避免将所有字段都映射到springdata中用于Elasticsearch的实体类,因为json文档中有100多个字段吗?

问题描述

我正在使用springdata API实现用于Elasticsearch(es)操作的spring-boot微服务。我在es中建立索引的文档很大,有多个字段(超过100个)。

有没有一种方法可以避免为Java中的Elasticsearch对象定义/硬编码实体类中的所有字段?

我的示例患者JSON可能像这样:

{
  "key_1":"value_1","key_2":"value_2","key_3":"value_3",.
         .
         .  

  "key_n":"value_n"
}

解决方法

如果您可以使用略有不同的形式将数据存储在Elastcisearch中,则可以使用以下内容:

按以下方式定义您的实体(为简洁起见,我省略了getter / setter):

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.patches import Patch

color = ('red','#00b050','#00b0f0','yellow')
objects = ('18-25','26-30','31-40','40-50')
y_pos = np.arange(len(objects))
performance = [13,18,16,3]
width = 0.35  # the width of the bars
plt.bar(y_pos,performance,align='center',color=color)
plt.xticks(y_pos,objects)
plt.ylim(0,20)  # this adds a little space at the top of the plot,to compensate for the annotation
plt.ylabel('%User',fontsize=16)
plt.title('Age of Respondents',fontsize=20)
width = 0.35

# map names to colors
cmap = dict(zip(performance,color))

# create the rectangles for the legend
patches = [Patch(color=v,label=k) for k,v in cmap.items()]

# add the legend
plt.legend(title='Number of Trips',labels=objects,handles=patches,bbox_to_anchor=(1.04,0.5),loc='center left',borderaxespad=0,fontsize=15,frameon=False)

# add the annotations
for y,x in zip(performance,y_pos):
    plt.annotate(f'{y}%\n',xy=(x,y),ha='center',va='center')

将其与Spring Data Elasticsearch存储库一起使用将创建具有以下映射的索引:

@Document(indexName = "innerdata")
public class InnerDataEntity {
    @Id
    private String id;

    @Field(type = FieldType.Object)
    private List<InnerData> innerData;
    
    static class InnerData {
        @Field(type = FieldType.Text)
        private String key;
        private String value;

    }
}

{ "innerdata": { "mappings": { "properties": { "id": { "fields": { "keyword": { "ignore_above": 256,"type": "keyword" } },"type": "text" },"innerData": { "properties": { "key": { "type": "text" } } } } } } } 属性是自动映射的,如果您也需要搜索它们,请添加value

然后您可以通过定义如下存储库来使用键值进行搜索:

FieldType.Text

并在控制器中使用它:

public interface InnerDataRepository extends ElasticsearchRepository<InnerDataEntity,String> {
    SearchHits<InnerDataEntity> searchByInnerData_Key(String key);
}

Elasticsearch中存储的数据如下:

@GetMapping("/{key}")
public SearchHits<InnerDataEntity> allByKey(@PathVariable String key) {

    return repository.searchByInnerData_Key(key);
}
,

感谢“ @ P.J。Meisch”,为我指出了正确的方向!

我通过执行文档(json)重组解决了该问题,该重组将在elasticsearch中建立索引。 通过将匿名患者ID保留在根级别并将其余患者详细信息保留在sub json中来完成。下面是我的Model类。

@Component
@Document(indexName = "manual_patients") // name must be lower case
@Getter
@Setter
@ToString(callSuper=true,includeFieldNames=true)
// @NoArgsConstructor
public class ManualPatient {

    @Id
    private String _id = UUID.randomUUID().toString();

    @ApiModelProperty(position = 0)
    private String patientId;

    private Map patientDetails;

    public ManualPatient(){}

    public ManualPatient( String patientId,Map patientDetails) {
        this.patientId = patientId;
        this.patientDetails = patientDetails;
    }
}