Skip to content

Allow field names with dots #2504

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1419,7 +1419,7 @@ public Object get(ElasticsearchPersistentProperty property) {

}

if (!fieldName.contains(".")) {
if (property.hasExplicitFieldName() || !fieldName.contains(".")) {
return target.get(fieldName);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
*/
String getFieldName();

/**
* @return {@literal true} if the field name comes from an explicit value in the field annotation
* @since 5.1
*/
boolean hasExplicitFieldName();

/**
* Returns whether the current property is a {@link SeqNoPrimaryTerm} property.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ public boolean storeEmptyValue() {
return storeEmptyValue;
}

protected boolean hasExplicitFieldName() {
@Override
public boolean hasExplicitFieldName() {
return StringUtils.hasText(getAnnotatedFieldName());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1947,6 +1947,48 @@ void shouldRespectFieldSettingForEmptyProperties() throws JSONException {
assertEquals(expected, json, true);
}

@Test // #2502
@DisplayName("should write entity with dotted field name")
void shouldWriteEntityWithDottedFieldName() throws JSONException {

@Language("JSON")
var expected = """
{
"_class": "org.springframework.data.elasticsearch.core.convert.MappingElasticsearchConverterUnitTests$FieldNameDotsEntity",
"id": "42",
"dotted.field": "dotted field"
}
""";
var entity = new FieldNameDotsEntity();
entity.setId("42");
entity.setDottedField("dotted field");

Document document = Document.create();
mappingElasticsearchConverter.write(entity, document);
String json = document.toJson();

assertEquals(expected, json, true);
}

@Test // #2502
@DisplayName("should read entity with dotted field name")
void shouldReadEntityWithDottedFieldName() {

@Language("JSON")
String json = """
{
"id": "42",
"dotted.field": "dotted field"
}""";

Document document = Document.parse(json);

FieldNameDotsEntity entity = mappingElasticsearchConverter.read(FieldNameDotsEntity.class, document);

assertThat(entity.id).isEqualTo("42");
assertThat(entity.getDottedField()).isEqualTo("dotted field");
}

// region entities
public static class Sample {
@Nullable public @ReadOnlyProperty String readOnly;
Expand Down Expand Up @@ -3150,6 +3192,31 @@ public void setMapToNotWriteWhenEmpty(@Nullable Map<String, String> mapToNotWrit
this.mapToNotWriteWhenEmpty = mapToNotWriteWhenEmpty;
}
}
static class FieldNameDotsEntity {
@Id
@Nullable private String id;
@Nullable
@Field(name = "dotted.field", type = FieldType.Text) private String dottedField;

@Nullable
public String getId() {
return id;
}

public void setId(@Nullable String id) {
this.id = id;
}

@Nullable
public String getDottedField() {
return dottedField;
}

public void setDottedField(@Nullable String dottedField) {
this.dottedField = dottedField;
}
}

// endregion

private static String reverse(Object o) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,14 @@ void shouldWriteSourceExcludes() {
indexOps.createWithMapping();
}

@Test // #2502
@DisplayName(" should write mapping with field name with dots")
void shouldWriteMappingWithFieldNameWithDots() {

IndexOperations indexOps = operations.indexOps(FieldNameDotsEntity.class);
indexOps.createWithMapping();
}

// region Entities
@Document(indexName = "#{@indexNameProvider.indexName()}")
static class Book {
Expand Down Expand Up @@ -901,5 +909,12 @@ private static class EntityWithAllTypes {
@Nullable
@Field(type = FieldType.Dense_Vector, dims = 1) String denseVectorField;
}
@Document(indexName = "#{@indexNameProvider.indexName()}")
private static class FieldNameDotsEntity {
@Id
@Nullable private String id;
@Nullable
@Field(name = "dotted.field", type = Text) private String dottedField;
}
// endregion
}
Original file line number Diff line number Diff line change
Expand Up @@ -1065,6 +1065,30 @@ void shouldNotWriteMappingForPropertyWithIndexedIndexNameAnotation() throws JSON

assertEquals(expected, mapping, true);
}

@Test // #2502
@DisplayName("should use custom name with dots")
void shouldUseCustomNameWithDots() throws JSONException {

var expected = """
{
"properties": {
"_class": {
"type": "keyword",
"index": false,
"doc_values": false
},
"dotted.field": {
"type": "text"
}
}
}
""";
String mapping = getMappingBuilder().buildPropertyMapping(FieldNameDotsEntity.class);

assertEquals(expected, mapping, true);
}

// region entities

@Document(indexName = "ignore-above-index")
Expand Down Expand Up @@ -2220,8 +2244,14 @@ private static class IndexedIndexNameEntity {
@Nullable
@Field(type = Text) private String someText;
@Nullable
@IndexedIndexName
private String storedIndexName;
@IndexedIndexName private String storedIndexName;
}

private static class FieldNameDotsEntity {
@Id
@Nullable private String id;
@Nullable
@Field(name = "dotted.field", type = Text) private String dottedField;
}
// endregion
}