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
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
if (!property.storeEmptyValue() && hasEmptyValue(value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (property.hasPropertyValueConverter()) {
|
||||
value = propertyConverterWrite(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")
|
||||
protected void writeProperty(ElasticsearchPersistentProperty property, Object value, MapValueAccessor sink) {
|
||||
|
||||
|
@ -74,6 +74,13 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
||||
*/
|
||||
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
|
||||
* @since 4.1
|
||||
|
@ -82,6 +82,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
private final @Nullable String annotatedFieldName;
|
||||
@Nullable private PropertyValueConverter propertyValueConverter;
|
||||
private final boolean storeNullValue;
|
||||
private final boolean storeEmptyValue;
|
||||
|
||||
public SimpleElasticsearchPersistentProperty(Property property,
|
||||
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
@ -106,6 +107,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
initPropertyValueConverter();
|
||||
|
||||
storeNullValue = isField && getRequiredAnnotation(Field.class).storeNullValue();
|
||||
storeEmptyValue = isField ? getRequiredAnnotation(Field.class).storeEmptyValue() : true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,6 +136,11 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
return storeNullValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean storeEmptyValue() {
|
||||
return storeEmptyValue;
|
||||
}
|
||||
|
||||
protected boolean hasExplicitFieldName() {
|
||||
return StringUtils.hasText(getAnnotatedFieldName());
|
||||
}
|
||||
|
@ -1893,6 +1893,35 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
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
|
||||
public static class Sample {
|
||||
@Nullable public @ReadOnlyProperty String readOnly;
|
||||
@ -2974,6 +3003,91 @@ public class MappingElasticsearchConverterUnitTests {
|
||||
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
|
||||
|
||||
private static String reverse(Object o) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user