|
15 | 15 | */
|
16 | 16 | package org.springframework.data.elasticsearch;
|
17 | 17 |
|
| 18 | +import static co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders.match; |
| 19 | +import static java.util.UUID.randomUUID; |
18 | 20 | import static org.assertj.core.api.Assertions.*;
|
19 | 21 | import static org.springframework.data.elasticsearch.utils.IdGenerator.*;
|
20 | 22 |
|
|
28 | 30 |
|
29 | 31 | import org.jetbrains.annotations.NotNull;
|
30 | 32 | import org.junit.jupiter.api.BeforeEach;
|
| 33 | +import org.junit.jupiter.api.DisplayName; |
31 | 34 | import org.junit.jupiter.api.Order;
|
32 | 35 | import org.junit.jupiter.api.Test;
|
33 | 36 | import org.springframework.beans.factory.annotation.Autowired;
|
|
37 | 40 | import org.springframework.data.elasticsearch.annotations.FieldType;
|
38 | 41 | import org.springframework.data.elasticsearch.annotations.InnerField;
|
39 | 42 | import org.springframework.data.elasticsearch.annotations.MultiField;
|
| 43 | +import org.springframework.data.elasticsearch.client.elc.NativeQuery; |
40 | 44 | import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
|
41 | 45 | import org.springframework.data.elasticsearch.core.IndexOperations;
|
42 | 46 | import org.springframework.data.elasticsearch.core.SearchHits;
|
@@ -373,6 +377,42 @@ public void shouldIndexAndSearchMapAsNestedType() {
|
373 | 377 | assertThat(books.getSearchHit(0).getContent().getId()).isEqualTo(book2.getId());
|
374 | 378 | }
|
375 | 379 |
|
| 380 | + @Test // #2952 |
| 381 | + @DisplayName("should handle null and empty field parameters in the mapping process") |
| 382 | + void shouldSupportMappingNullAndEmptyFieldParameter() { |
| 383 | + // Given |
| 384 | + operations.indexOps(MultiFieldWithNullEmptyParameters.class).createWithMapping(); |
| 385 | + List<IndexQuery> indexQueries = new ArrayList<>(); |
| 386 | + MultiFieldWithNullEmptyParameters nullObj = new MultiFieldWithNullEmptyParameters(); |
| 387 | + nullObj.addFieldWithInner(randomUUID().toString()); |
| 388 | + MultiFieldWithNullEmptyParameters objWithValue = new MultiFieldWithNullEmptyParameters(); |
| 389 | + objWithValue.addEmptyField(randomUUID().toString()); |
| 390 | + |
| 391 | + IndexQuery indexQuery1 = new IndexQuery(); |
| 392 | + indexQuery1.setId(nextIdAsString()); |
| 393 | + indexQuery1.setObject(nullObj); |
| 394 | + indexQueries.add(indexQuery1); |
| 395 | + |
| 396 | + IndexQuery indexQuery2 = new IndexQuery(); |
| 397 | + indexQuery2.setId(nextIdAsString()); |
| 398 | + indexQuery2.setObject(objWithValue); |
| 399 | + indexQueries.add(indexQuery2); |
| 400 | + |
| 401 | + // When |
| 402 | + operations.bulkIndex(indexQueries, MultiFieldWithNullEmptyParameters.class); |
| 403 | + |
| 404 | + // Then |
| 405 | + SearchHits<MultiFieldWithNullEmptyParameters> nullResults = operations.search( |
| 406 | + NativeQuery.builder().withQuery(match(bm -> bm.field("empty-field").query("EMPTY"))).build(), |
| 407 | + MultiFieldWithNullEmptyParameters.class); |
| 408 | + assertThat(nullResults.getSearchHits()).hasSize(1); |
| 409 | + |
| 410 | + nullResults = operations.search( |
| 411 | + NativeQuery.builder().withQuery(match(bm -> bm.field("inner-field.prefix").query("EMPTY"))).build(), |
| 412 | + MultiFieldWithNullEmptyParameters.class); |
| 413 | + assertThat(nullResults.getSearchHits()).hasSize(1); |
| 414 | + } |
| 415 | + |
376 | 416 | @NotNull
|
377 | 417 | abstract protected Query getNestedQuery4();
|
378 | 418 |
|
@@ -622,4 +662,40 @@ public void setName(@Nullable String name) {
|
622 | 662 | }
|
623 | 663 | }
|
624 | 664 |
|
| 665 | + @Document(indexName = "#{@indexNameProvider.indexName()}-multi-field") |
| 666 | + static class MultiFieldWithNullEmptyParameters { |
| 667 | + @Nullable |
| 668 | + @MultiField(mainField = @Field(name = "empty-field", type = FieldType.Keyword, nullValue = "EMPTY", |
| 669 | + storeNullValue = true)) private List<String> emptyField; |
| 670 | + |
| 671 | + @Nullable |
| 672 | + @MultiField(mainField = @Field(name = "inner-field", type = FieldType.Text, storeNullValue = true), |
| 673 | + otherFields = { @InnerField(suffix = "prefix", type = FieldType.Keyword, |
| 674 | + nullValue = "EMPTY") }) private List<String> fieldWithInner; |
| 675 | + |
| 676 | + public List<String> getEmptyField() { |
| 677 | + if (emptyField == null) { |
| 678 | + emptyField = new ArrayList<>(); |
| 679 | + } |
| 680 | + |
| 681 | + return emptyField; |
| 682 | + } |
| 683 | + |
| 684 | + public void addEmptyField(String value) { |
| 685 | + getEmptyField().add(value); |
| 686 | + } |
| 687 | + |
| 688 | + public List<String> getFieldWithInner() { |
| 689 | + if (fieldWithInner == null) { |
| 690 | + fieldWithInner = new ArrayList<>(); |
| 691 | + } |
| 692 | + |
| 693 | + return fieldWithInner; |
| 694 | + } |
| 695 | + |
| 696 | + public void addFieldWithInner(@Nullable String value) { |
| 697 | + getFieldWithInner().add(value); |
| 698 | + } |
| 699 | + } |
| 700 | + |
625 | 701 | }
|
0 commit comments