Skip to content

Commit e7c9bf2

Browse files
authored
Add option to specify if empty property should not be sent to Elasticsearch.
Original Pull Request #2482 Closes #2290
1 parent b4c3e25 commit e7c9bf2

File tree

5 files changed

+151
-1
lines changed

5 files changed

+151
-1
lines changed

src/main/java/org/springframework/data/elasticsearch/annotations/Field.java

+8
Original file line numberDiff line numberDiff line change
@@ -210,4 +210,12 @@
210210
* @since 4.3
211211
*/
212212
boolean excludeFromSource() default false;
213+
214+
/**
215+
* when this field is a {{@link String}}, a {{@link java.util.Collection}} or a {{@link java.util.Map}} that is empty
216+
* this property controlls whether the empty value is sent to Elasticsearch.
217+
*
218+
* @since 5.1
219+
*/
220+
boolean storeEmptyValue() default true;
213221
}

src/main/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverter.java

+14
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,10 @@ private void writeProperties(ElasticsearchPersistentEntity<?> entity, Persistent
960960
continue;
961961
}
962962

963+
if (!property.storeEmptyValue() && hasEmptyValue(value)) {
964+
continue;
965+
}
966+
963967
if (property.hasPropertyValueConverter()) {
964968
value = propertyConverterWrite(property, value);
965969
sink.set(property, value);
@@ -988,6 +992,16 @@ private void writeProperties(ElasticsearchPersistentEntity<?> entity, Persistent
988992
}
989993
}
990994

995+
private static boolean hasEmptyValue(Object value) {
996+
997+
if (value instanceof String s && s.isEmpty() || value instanceof Collection<?> c && c.isEmpty()
998+
|| value instanceof Map<?, ?> m && m.isEmpty()) {
999+
return true;
1000+
}
1001+
1002+
return false;
1003+
}
1004+
9911005
@SuppressWarnings("unchecked")
9921006
protected void writeProperty(ElasticsearchPersistentProperty property, Object value, MapValueAccessor sink) {
9931007

src/main/java/org/springframework/data/elasticsearch/core/mapping/ElasticsearchPersistentProperty.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
7474
*/
7575
boolean storeNullValue();
7676

77+
/**
78+
* @return true if empty values ({{@link String}}, or {{@link java.util.Collection}} or {{@link java.util.Map}})
79+
* should be store in Elasticsearch.
80+
* @since 5.1
81+
*/
82+
boolean storeEmptyValue();
83+
7784
/**
7885
* @return {@literal true} if this is a GeoPoint property
7986
* @since 4.1
@@ -100,7 +107,7 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
100107

101108
/**
102109
* @return {@literal true} if this is a property annotated with
103-
* {@link org.springframework.data.elasticsearch.annotations.IndexedIndexName}.
110+
* {@link org.springframework.data.elasticsearch.annotations.IndexedIndexName}.
104111
* @since 5.1
105112
*/
106113
boolean isIndexedIndexNameProperty();

src/main/java/org/springframework/data/elasticsearch/core/mapping/SimpleElasticsearchPersistentProperty.java

+7
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public class SimpleElasticsearchPersistentProperty extends
8282
private final @Nullable String annotatedFieldName;
8383
@Nullable private PropertyValueConverter propertyValueConverter;
8484
private final boolean storeNullValue;
85+
private final boolean storeEmptyValue;
8586

8687
public SimpleElasticsearchPersistentProperty(Property property,
8788
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
@@ -106,6 +107,7 @@ public SimpleElasticsearchPersistentProperty(Property property,
106107
initPropertyValueConverter();
107108

108109
storeNullValue = isField && getRequiredAnnotation(Field.class).storeNullValue();
110+
storeEmptyValue = isField ? getRequiredAnnotation(Field.class).storeEmptyValue() : true;
109111
}
110112

111113
@Override
@@ -134,6 +136,11 @@ public boolean storeNullValue() {
134136
return storeNullValue;
135137
}
136138

139+
@Override
140+
public boolean storeEmptyValue() {
141+
return storeEmptyValue;
142+
}
143+
137144
protected boolean hasExplicitFieldName() {
138145
return StringUtils.hasText(getAnnotatedFieldName());
139146
}

src/test/java/org/springframework/data/elasticsearch/core/convert/MappingElasticsearchConverterUnitTests.java

+114
Original file line numberDiff line numberDiff line change
@@ -1893,6 +1893,35 @@ void shouldNotWriteIdPropertyToDocumentSourceIfConfiguredSo() throws JSONExcepti
18931893
assertEquals(expected, json, true);
18941894
}
18951895

1896+
@Test // #2290
1897+
@DisplayName("should respect field setting for empty properties")
1898+
void shouldRespectFieldSettingForEmptyProperties() throws JSONException {
1899+
@Language("JSON")
1900+
var expected = """
1901+
{
1902+
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$EntityWithPropertiesThatMightBeEmpty",
1903+
"id": "42",
1904+
"stringToWriteWhenEmpty": "",
1905+
"listToWriteWhenEmpty": [],
1906+
"mapToWriteWhenEmpty": {}
1907+
}
1908+
""";
1909+
var entity = new EntityWithPropertiesThatMightBeEmpty();
1910+
entity.setId("42");
1911+
entity.setStringToWriteWhenEmpty("");
1912+
entity.setStringToNotWriteWhenEmpty("");
1913+
entity.setListToWriteWhenEmpty(emptyList());
1914+
entity.setListToNotWriteWhenEmpty(emptyList());
1915+
entity.setMapToWriteWhenEmpty(emptyMap());
1916+
entity.setMapToNotWriteWhenEmpty(emptyMap());
1917+
1918+
Document document = Document.create();
1919+
mappingElasticsearchConverter.write(entity, document);
1920+
String json = document.toJson();
1921+
1922+
assertEquals(expected, json, true);
1923+
}
1924+
18961925
// region entities
18971926
public static class Sample {
18981927
@Nullable public @ReadOnlyProperty String readOnly;
@@ -2974,6 +3003,91 @@ public void setText(@Nullable String text) {
29743003
this.text = text;
29753004
}
29763005
}
3006+
3007+
static class EntityWithPropertiesThatMightBeEmpty {
3008+
@Nullable private String id;
3009+
3010+
@Field(type = FieldType.Text)
3011+
@Nullable private String stringToWriteWhenEmpty;
3012+
3013+
@Field(type = FieldType.Text, storeEmptyValue = false)
3014+
@Nullable private String stringToNotWriteWhenEmpty;
3015+
3016+
@Field(type = FieldType.Nested)
3017+
@Nullable private List<String> listToWriteWhenEmpty;
3018+
3019+
@Field(type = FieldType.Nested, storeEmptyValue = false)
3020+
@Nullable private List<String> listToNotWriteWhenEmpty;
3021+
3022+
@Field(type = FieldType.Nested)
3023+
@Nullable private Map<String, String> mapToWriteWhenEmpty;
3024+
3025+
@Field(type = FieldType.Nested, storeEmptyValue = false)
3026+
@Nullable private Map<String, String> mapToNotWriteWhenEmpty;
3027+
3028+
@Nullable
3029+
public String getId() {
3030+
return id;
3031+
}
3032+
3033+
public void setId(@Nullable String id) {
3034+
this.id = id;
3035+
}
3036+
3037+
@Nullable
3038+
public String getStringToWriteWhenEmpty() {
3039+
return stringToWriteWhenEmpty;
3040+
}
3041+
3042+
public void setStringToWriteWhenEmpty(@Nullable String stringToWriteWhenEmpty) {
3043+
this.stringToWriteWhenEmpty = stringToWriteWhenEmpty;
3044+
}
3045+
3046+
@Nullable
3047+
public String getStringToNotWriteWhenEmpty() {
3048+
return stringToNotWriteWhenEmpty;
3049+
}
3050+
3051+
public void setStringToNotWriteWhenEmpty(@Nullable String stringToNotWriteWhenEmpty) {
3052+
this.stringToNotWriteWhenEmpty = stringToNotWriteWhenEmpty;
3053+
}
3054+
3055+
@Nullable
3056+
public List<String> getListToWriteWhenEmpty() {
3057+
return listToWriteWhenEmpty;
3058+
}
3059+
3060+
public void setListToWriteWhenEmpty(@Nullable List<String> listToWriteWhenEmpty) {
3061+
this.listToWriteWhenEmpty = listToWriteWhenEmpty;
3062+
}
3063+
3064+
@Nullable
3065+
public List<String> getListToNotWriteWhenEmpty() {
3066+
return listToNotWriteWhenEmpty;
3067+
}
3068+
3069+
public void setListToNotWriteWhenEmpty(@Nullable List<String> listToNotWriteWhenEmpty) {
3070+
this.listToNotWriteWhenEmpty = listToNotWriteWhenEmpty;
3071+
}
3072+
3073+
@Nullable
3074+
public Map<String, String> getMapToWriteWhenEmpty() {
3075+
return mapToWriteWhenEmpty;
3076+
}
3077+
3078+
public void setMapToWriteWhenEmpty(@Nullable Map<String, String> mapToWriteWhenEmpty) {
3079+
this.mapToWriteWhenEmpty = mapToWriteWhenEmpty;
3080+
}
3081+
3082+
@Nullable
3083+
public Map<String, String> getMapToNotWriteWhenEmpty() {
3084+
return mapToNotWriteWhenEmpty;
3085+
}
3086+
3087+
public void setMapToNotWriteWhenEmpty(@Nullable Map<String, String> mapToNotWriteWhenEmpty) {
3088+
this.mapToNotWriteWhenEmpty = mapToNotWriteWhenEmpty;
3089+
}
3090+
}
29773091
// endregion
29783092

29793093
private static String reverse(Object o) {

0 commit comments

Comments
 (0)