mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-28 23:02:12 +00:00
Add option to specify if empty property should not be sent to Elasticsearch.
Original Pull Request #2482 Closes #2290
This commit is contained in:
parent
b4c3e25a60
commit
e7c9bf20f6
@ -210,4 +210,12 @@ public @interface Field {
|
|||||||
* @since 4.3
|
* @since 4.3
|
||||||
*/
|
*/
|
||||||
boolean excludeFromSource() default false;
|
boolean excludeFromSource() default false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* when this field is a {{@link String}}, a {{@link java.util.Collection}} or a {{@link java.util.Map}} that is empty
|
||||||
|
* this property controlls whether the empty value is sent to Elasticsearch.
|
||||||
|
*
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
boolean storeEmptyValue() default true;
|
||||||
}
|
}
|
||||||
|
@ -960,6 +960,10 @@ public class MappingElasticsearchConverter
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!property.storeEmptyValue() && hasEmptyValue(value)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (property.hasPropertyValueConverter()) {
|
if (property.hasPropertyValueConverter()) {
|
||||||
value = propertyConverterWrite(property, value);
|
value = propertyConverterWrite(property, value);
|
||||||
sink.set(property, value);
|
sink.set(property, value);
|
||||||
@ -988,6 +992,16 @@ public class MappingElasticsearchConverter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean hasEmptyValue(Object value) {
|
||||||
|
|
||||||
|
if (value instanceof String s && s.isEmpty() || value instanceof Collection<?> c && c.isEmpty()
|
||||||
|
|| value instanceof Map<?, ?> m && m.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void writeProperty(ElasticsearchPersistentProperty property, Object value, MapValueAccessor sink) {
|
protected void writeProperty(ElasticsearchPersistentProperty property, Object value, MapValueAccessor sink) {
|
||||||
|
|
||||||
|
@ -74,6 +74,13 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
|||||||
*/
|
*/
|
||||||
boolean storeNullValue();
|
boolean storeNullValue();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if empty values ({{@link String}}, or {{@link java.util.Collection}} or {{@link java.util.Map}})
|
||||||
|
* should be store in Elasticsearch.
|
||||||
|
* @since 5.1
|
||||||
|
*/
|
||||||
|
boolean storeEmptyValue();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@literal true} if this is a GeoPoint property
|
* @return {@literal true} if this is a GeoPoint property
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
@ -100,7 +107,7 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {@literal true} if this is a property annotated with
|
* @return {@literal true} if this is a property annotated with
|
||||||
* {@link org.springframework.data.elasticsearch.annotations.IndexedIndexName}.
|
* {@link org.springframework.data.elasticsearch.annotations.IndexedIndexName}.
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
boolean isIndexedIndexNameProperty();
|
boolean isIndexedIndexNameProperty();
|
||||||
|
@ -82,6 +82,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
|||||||
private final @Nullable String annotatedFieldName;
|
private final @Nullable String annotatedFieldName;
|
||||||
@Nullable private PropertyValueConverter propertyValueConverter;
|
@Nullable private PropertyValueConverter propertyValueConverter;
|
||||||
private final boolean storeNullValue;
|
private final boolean storeNullValue;
|
||||||
|
private final boolean storeEmptyValue;
|
||||||
|
|
||||||
public SimpleElasticsearchPersistentProperty(Property property,
|
public SimpleElasticsearchPersistentProperty(Property property,
|
||||||
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||||
@ -106,6 +107,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
|||||||
initPropertyValueConverter();
|
initPropertyValueConverter();
|
||||||
|
|
||||||
storeNullValue = isField && getRequiredAnnotation(Field.class).storeNullValue();
|
storeNullValue = isField && getRequiredAnnotation(Field.class).storeNullValue();
|
||||||
|
storeEmptyValue = isField ? getRequiredAnnotation(Field.class).storeEmptyValue() : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -134,6 +136,11 @@ public class SimpleElasticsearchPersistentProperty extends
|
|||||||
return storeNullValue;
|
return storeNullValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean storeEmptyValue() {
|
||||||
|
return storeEmptyValue;
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean hasExplicitFieldName() {
|
protected boolean hasExplicitFieldName() {
|
||||||
return StringUtils.hasText(getAnnotatedFieldName());
|
return StringUtils.hasText(getAnnotatedFieldName());
|
||||||
}
|
}
|
||||||
|
@ -1893,6 +1893,35 @@ public class MappingElasticsearchConverterUnitTests {
|
|||||||
assertEquals(expected, json, true);
|
assertEquals(expected, json, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test // #2290
|
||||||
|
@DisplayName("should respect field setting for empty properties")
|
||||||
|
void shouldRespectFieldSettingForEmptyProperties() throws JSONException {
|
||||||
|
@Language("JSON")
|
||||||
|
var expected = """
|
||||||
|
{
|
||||||
|
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$EntityWithPropertiesThatMightBeEmpty",
|
||||||
|
"id": "42",
|
||||||
|
"stringToWriteWhenEmpty": "",
|
||||||
|
"listToWriteWhenEmpty": [],
|
||||||
|
"mapToWriteWhenEmpty": {}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
var entity = new EntityWithPropertiesThatMightBeEmpty();
|
||||||
|
entity.setId("42");
|
||||||
|
entity.setStringToWriteWhenEmpty("");
|
||||||
|
entity.setStringToNotWriteWhenEmpty("");
|
||||||
|
entity.setListToWriteWhenEmpty(emptyList());
|
||||||
|
entity.setListToNotWriteWhenEmpty(emptyList());
|
||||||
|
entity.setMapToWriteWhenEmpty(emptyMap());
|
||||||
|
entity.setMapToNotWriteWhenEmpty(emptyMap());
|
||||||
|
|
||||||
|
Document document = Document.create();
|
||||||
|
mappingElasticsearchConverter.write(entity, document);
|
||||||
|
String json = document.toJson();
|
||||||
|
|
||||||
|
assertEquals(expected, json, true);
|
||||||
|
}
|
||||||
|
|
||||||
// region entities
|
// region entities
|
||||||
public static class Sample {
|
public static class Sample {
|
||||||
@Nullable public @ReadOnlyProperty String readOnly;
|
@Nullable public @ReadOnlyProperty String readOnly;
|
||||||
@ -2974,6 +3003,91 @@ public class MappingElasticsearchConverterUnitTests {
|
|||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class EntityWithPropertiesThatMightBeEmpty {
|
||||||
|
@Nullable private String id;
|
||||||
|
|
||||||
|
@Field(type = FieldType.Text)
|
||||||
|
@Nullable private String stringToWriteWhenEmpty;
|
||||||
|
|
||||||
|
@Field(type = FieldType.Text, storeEmptyValue = false)
|
||||||
|
@Nullable private String stringToNotWriteWhenEmpty;
|
||||||
|
|
||||||
|
@Field(type = FieldType.Nested)
|
||||||
|
@Nullable private List<String> listToWriteWhenEmpty;
|
||||||
|
|
||||||
|
@Field(type = FieldType.Nested, storeEmptyValue = false)
|
||||||
|
@Nullable private List<String> listToNotWriteWhenEmpty;
|
||||||
|
|
||||||
|
@Field(type = FieldType.Nested)
|
||||||
|
@Nullable private Map<String, String> mapToWriteWhenEmpty;
|
||||||
|
|
||||||
|
@Field(type = FieldType.Nested, storeEmptyValue = false)
|
||||||
|
@Nullable private Map<String, String> mapToNotWriteWhenEmpty;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(@Nullable String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getStringToWriteWhenEmpty() {
|
||||||
|
return stringToWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringToWriteWhenEmpty(@Nullable String stringToWriteWhenEmpty) {
|
||||||
|
this.stringToWriteWhenEmpty = stringToWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String getStringToNotWriteWhenEmpty() {
|
||||||
|
return stringToNotWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStringToNotWriteWhenEmpty(@Nullable String stringToNotWriteWhenEmpty) {
|
||||||
|
this.stringToNotWriteWhenEmpty = stringToNotWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public List<String> getListToWriteWhenEmpty() {
|
||||||
|
return listToWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListToWriteWhenEmpty(@Nullable List<String> listToWriteWhenEmpty) {
|
||||||
|
this.listToWriteWhenEmpty = listToWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public List<String> getListToNotWriteWhenEmpty() {
|
||||||
|
return listToNotWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListToNotWriteWhenEmpty(@Nullable List<String> listToNotWriteWhenEmpty) {
|
||||||
|
this.listToNotWriteWhenEmpty = listToNotWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Map<String, String> getMapToWriteWhenEmpty() {
|
||||||
|
return mapToWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapToWriteWhenEmpty(@Nullable Map<String, String> mapToWriteWhenEmpty) {
|
||||||
|
this.mapToWriteWhenEmpty = mapToWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Map<String, String> getMapToNotWriteWhenEmpty() {
|
||||||
|
return mapToNotWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMapToNotWriteWhenEmpty(@Nullable Map<String, String> mapToNotWriteWhenEmpty) {
|
||||||
|
this.mapToNotWriteWhenEmpty = mapToNotWriteWhenEmpty;
|
||||||
|
}
|
||||||
|
}
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
private static String reverse(Object o) {
|
private static String reverse(Object o) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user