I'm struggling with mappings some field. I looked for an answer but couldn't find anything solving my case. Let's cut to the chase.
I have my document class
@Doucment
public class DocumentClass {
@Field(type = FieldType.Nested)
private EmployeeId employeeId;
}
An EmployeeId is wrapper for my uuid identifier. This object has nothing but just getters and setters and jackson annotations. The thing is that object extends some base class so such objects like EmployeeId can inherit this object. This super class has field id and this causes the problem. When I post some data to elasticsearch then it looks like this:
{
"employeeId": {
"id": "someUUID"
}
}
But I want to map this to be like:
{
"employeeId": "someUUID"
}
I wonder if there is a way to flatten this object.
CodePudding user response:
If I get it right, you want to convert your EmployeeId
class to a String and back. You have 2 possibilities to do that:
Using a property converter
If you only want to convert an EmployeeId
in this entity and might keep it as it is in another, you should use a property converter that is only registered for this property:
import org.springframework.data.elasticsearch.core.mapping.PropertyValueConverter;
public class EmployeeIdConverter implements PropertyValueConverter {
@Override
public Object write(Object value) {
return value instanceof EmployeeId employeeId ? employeeId.getId() : value.toString();
}
@Override
public Object read(Object value) {
return new EmployeeId(value.toString());
}
}
This converter must be registered on the property, notice that the field type is set to Keyword
as it probably should not be analysed:
import org.springframework.data.elasticsearch.annotations.ValueConverter;
@Document
public class DocumentClass {
@Field(type = FieldType.Keyword)
@ValueConverter(EmployeeIdConverter.class)
private EmployeeId employeeId;
}
Using a global converter
If you are using this EmployeeId
at several places you might want register globally 2 converters for the two conversion directions:
@WritingConverter
public class EmployeeIdToString implements Converter<EmployeeId, String>{
@Nullable
@Override
public String convert(EmployeeId employeeId) {
return employeeId.getId();
}
}
@ReadingConverter
public class StringToEmployeeId implements Converter<String, EmployeeId>{
@Nullable
@Override
public EmployeeId convert(String id) {
return new EmployeeId(id);
}
}
To register these, you need to provide a custom client configuration (see the documentation):
@Configuration
public class MyClientConfig extends ElasticsearchConfiguration {
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder()
.connectedTo("localhost:9200")
.build();
}
@Override
public ElasticsearchCustomConversions elasticsearchCustomConversions() {
Collection<Converter<?, ?>> converters = new ArrayList<>();
converters.add(new EmployeeIdToString());
converters.add(new StringToEmployeeId());
return new ElasticsearchCustomConversions(converters);
}
}
In this case, only the field type needs to be adjusted
@Document
public class DocumentClass {
@Field(type = FieldType.Keyword)
private EmployeeId employeeId;
}
CodePudding user response:
I am guessing you have an Id field which is a string.
You need to put a @JsonValue annotation on that field to make jackson serialize it the way you want.
Field annotated by JsonValue will be used to serialize your pojo into json.
If your Id field is private, then add the annotation on the getter of that field.