mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-01 09:42:11 +00:00
DATAES-920 - Add parameter to @Field annotation to store null values.
Original PR: #516
This commit is contained in:
parent
ef1cbc35f6
commit
d03510528b
@ -154,4 +154,11 @@ public @interface Field {
|
|||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
int maxShingleSize() default -1;
|
int maxShingleSize() default -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if true, the field will be stored in Elasticsearch even if it has a null value
|
||||||
|
*
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
boolean storeNullValue() default false;
|
||||||
}
|
}
|
||||||
|
@ -497,6 +497,11 @@ public class MappingElasticsearchConverter
|
|||||||
Object value = accessor.getProperty(property);
|
Object value = accessor.getProperty(property);
|
||||||
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
|
|
||||||
|
if (property.storeNullValue()) {
|
||||||
|
sink.set(property, null);
|
||||||
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,7 +802,8 @@ public class MappingElasticsearchConverter
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
org.springframework.data.elasticsearch.annotations.Field fieldAnnotation = property.findAnnotation(org.springframework.data.elasticsearch.annotations.Field.class);
|
org.springframework.data.elasticsearch.annotations.Field fieldAnnotation = property
|
||||||
|
.findAnnotation(org.springframework.data.elasticsearch.annotations.Field.class);
|
||||||
|
|
||||||
if (fieldAnnotation != null) {
|
if (fieldAnnotation != null) {
|
||||||
field.setFieldType(fieldAnnotation.type());
|
field.setFieldType(fieldAnnotation.type());
|
||||||
@ -864,14 +870,17 @@ public class MappingElasticsearchConverter
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(ElasticsearchPersistentProperty property, Object value) {
|
public void set(ElasticsearchPersistentProperty property, @Nullable Object value) {
|
||||||
|
|
||||||
if (property.isIdProperty()) {
|
if (value != null) {
|
||||||
((Document) target).setId(value.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (property.isVersionProperty()) {
|
if (property.isIdProperty()) {
|
||||||
((Document) target).setVersion((Long) value);
|
((Document) target).setId(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property.isVersionProperty()) {
|
||||||
|
((Document) target).setVersion((Long) value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
target.put(property.getFieldName(), value);
|
target.put(property.getFieldName(), value);
|
||||||
|
@ -96,6 +96,12 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
|||||||
*/
|
*/
|
||||||
boolean isReadable();
|
boolean isReadable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {@literal true} if null values should be stored in Elasticsearch
|
||||||
|
* @since 4.1
|
||||||
|
*/
|
||||||
|
boolean storeNullValue();
|
||||||
|
|
||||||
enum PropertyToFieldNameConverter implements Converter<ElasticsearchPersistentProperty, String> {
|
enum PropertyToFieldNameConverter implements Converter<ElasticsearchPersistentProperty, String> {
|
||||||
|
|
||||||
INSTANCE;
|
INSTANCE;
|
||||||
|
@ -64,6 +64,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
|||||||
private final boolean isSeqNoPrimaryTerm;
|
private final boolean isSeqNoPrimaryTerm;
|
||||||
private final @Nullable String annotatedFieldName;
|
private final @Nullable String annotatedFieldName;
|
||||||
@Nullable private ElasticsearchPersistentPropertyConverter propertyConverter;
|
@Nullable private ElasticsearchPersistentPropertyConverter propertyConverter;
|
||||||
|
private boolean storeNullValue;
|
||||||
|
|
||||||
public SimpleElasticsearchPersistentProperty(Property property,
|
public SimpleElasticsearchPersistentProperty(Property property,
|
||||||
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||||
@ -85,6 +86,8 @@ public class SimpleElasticsearchPersistentProperty extends
|
|||||||
this.isParent = isAnnotationPresent(Parent.class);
|
this.isParent = isAnnotationPresent(Parent.class);
|
||||||
this.isSeqNoPrimaryTerm = SeqNoPrimaryTerm.class.isAssignableFrom(getRawType());
|
this.isSeqNoPrimaryTerm = SeqNoPrimaryTerm.class.isAssignableFrom(getRawType());
|
||||||
|
|
||||||
|
boolean isField = isAnnotationPresent(Field.class);
|
||||||
|
|
||||||
if (isVersionProperty() && !getType().equals(Long.class)) {
|
if (isVersionProperty() && !getType().equals(Long.class)) {
|
||||||
throw new MappingException(String.format("Version property %s must be of type Long!", property.getName()));
|
throw new MappingException(String.format("Version property %s must be of type Long!", property.getName()));
|
||||||
}
|
}
|
||||||
@ -98,11 +101,13 @@ public class SimpleElasticsearchPersistentProperty extends
|
|||||||
throw new MappingException(String.format("Parent property %s must be of type String!", property.getName()));
|
throw new MappingException(String.format("Parent property %s must be of type String!", property.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAnnotationPresent(Field.class) && isAnnotationPresent(MultiField.class)) {
|
if (isField && isAnnotationPresent(MultiField.class)) {
|
||||||
throw new MappingException("@Field annotation must not be used on a @MultiField property.");
|
throw new MappingException("@Field annotation must not be used on a @MultiField property.");
|
||||||
}
|
}
|
||||||
|
|
||||||
initDateConverter();
|
initDateConverter();
|
||||||
|
|
||||||
|
storeNullValue = isField && getRequiredAnnotation(Field.class).storeNullValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -126,6 +131,11 @@ public class SimpleElasticsearchPersistentProperty extends
|
|||||||
return !isTransient() && !isSeqNoPrimaryTermProperty();
|
return !isTransient() && !isSeqNoPrimaryTermProperty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean storeNullValue() {
|
||||||
|
return storeNullValue;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes an {@link ElasticsearchPersistentPropertyConverter} if this property is annotated as a Field with type
|
* Initializes an {@link ElasticsearchPersistentPropertyConverter} if this property is annotated as a Field with type
|
||||||
* {@link FieldType#Date}, has a {@link DateFormat} set and if the type of the property is one of the Java8 temporal
|
* {@link FieldType#Date}, has a {@link DateFormat} set and if the type of the property is one of the Java8 temporal
|
||||||
|
@ -39,6 +39,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.DisplayName;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.core.convert.ConversionService;
|
import org.springframework.core.convert.ConversionService;
|
||||||
import org.springframework.core.convert.converter.Converter;
|
import org.springframework.core.convert.converter.Converter;
|
||||||
@ -616,7 +617,7 @@ public class MappingElasticsearchConverterUnitTests {
|
|||||||
assertEquals(expected, json, false);
|
assertEquals(expected, json, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test // DATAES-716
|
||||||
void shouldReadLocalDate() {
|
void shouldReadLocalDate() {
|
||||||
Document document = Document.create();
|
Document document = Document.create();
|
||||||
document.put("id", "4711");
|
document.put("id", "4711");
|
||||||
@ -813,6 +814,25 @@ public class MappingElasticsearchConverterUnitTests {
|
|||||||
assertEquals(expected, document.toJson(), false);
|
assertEquals(expected, document.toJson(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // DATAES-920
|
||||||
|
@DisplayName("should write null value if configured")
|
||||||
|
void shouldWriteNullValueIfConfigured() throws JSONException {
|
||||||
|
|
||||||
|
EntityWithNullField entity = new EntityWithNullField();
|
||||||
|
entity.setId("42");
|
||||||
|
|
||||||
|
String expected = "{\n" + //
|
||||||
|
" \"id\": \"42\",\n" + //
|
||||||
|
" \"saved\": null\n" + //
|
||||||
|
"}\n"; //
|
||||||
|
|
||||||
|
Document document = Document.create();
|
||||||
|
|
||||||
|
mappingElasticsearchConverter.write(entity, document);
|
||||||
|
|
||||||
|
assertEquals(expected, document.toJson(), false);
|
||||||
|
}
|
||||||
|
|
||||||
private String pointTemplate(String name, Point point) {
|
private String pointTemplate(String name, Point point) {
|
||||||
return String.format(Locale.ENGLISH, "\"%s\":{\"lat\":%.1f,\"lon\":%.1f}", name, point.getX(), point.getY());
|
return String.format(Locale.ENGLISH, "\"%s\":{\"lat\":%.1f,\"lon\":%.1f}", name, point.getX(), point.getY());
|
||||||
}
|
}
|
||||||
@ -1046,4 +1066,11 @@ public class MappingElasticsearchConverterUnitTests {
|
|||||||
@Id private String id;
|
@Id private String id;
|
||||||
private Object content;
|
private Object content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class EntityWithNullField {
|
||||||
|
@Id private String id;
|
||||||
|
@Field(type = FieldType.Text) private String notSaved;
|
||||||
|
@Field(type = FieldType.Text, storeNullValue = true) private String saved;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user