mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-05-30 08:42:10 +00:00
Custom property names must be used in SourceFilter and source fields.
Original Pull Request #1780 Closes #1778
This commit is contained in:
parent
7ace63485d
commit
79087c4ada
@ -19,7 +19,6 @@ import org.springframework.data.convert.EntityConverter;
|
||||
import org.springframework.data.elasticsearch.core.document.Document;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentEntity;
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.projection.ProjectionFactory;
|
||||
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
|
||||
@ -64,7 +63,13 @@ public interface ElasticsearchConverter
|
||||
return idValue.toString();
|
||||
}
|
||||
|
||||
return getConversionService().convert(idValue, String.class);
|
||||
String converted = getConversionService().convert(idValue, String.class);
|
||||
|
||||
if (converted == null) {
|
||||
return idValue.toString();
|
||||
}
|
||||
|
||||
return converted;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,29 +91,15 @@ public interface ElasticsearchConverter
|
||||
|
||||
// region query
|
||||
/**
|
||||
* Updates a {@link CriteriaQuery} by renaming the property names in the query to the correct mapped field names and
|
||||
* the values to the converted values if the {@link ElasticsearchPersistentProperty} for a property has a
|
||||
* Updates a {@link Query} by renaming the property names in the query to the correct mapped field names and the
|
||||
* values to the converted values if the {@link ElasticsearchPersistentProperty} for a property has a
|
||||
* {@link org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter}. If
|
||||
* domainClass is null or query is not a {@link CriteriaQuery}, it's a noop.
|
||||
* domainClass is null it's a noop.
|
||||
*
|
||||
* @param query the query that is internally updated
|
||||
* @param query the query that is internally updated, must not be {@literal null}
|
||||
* @param domainClass the class of the object that is searched with the query
|
||||
*/
|
||||
default void updateQuery(Query query, @Nullable Class<?> domainClass) {
|
||||
void updateQuery(Query query, @Nullable Class<?> domainClass);
|
||||
|
||||
if (domainClass != null && query instanceof CriteriaQuery) {
|
||||
updateCriteriaQuery((CriteriaQuery) query, domainClass);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a {@link CriteriaQuery} by renaming the property names in the query to the correct mapped field names and
|
||||
* the values to the converted values if the {@link ElasticsearchPersistentProperty} for a property has a
|
||||
* {@link org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter}.
|
||||
*
|
||||
* @param criteriaQuery the query that is internally updated, must not be {@literal null}
|
||||
* @param domainClass the class of the object that is searched with the query, must not be {@literal null}
|
||||
*/
|
||||
void updateCriteriaQuery(CriteriaQuery criteriaQuery, Class<?> domainClass);
|
||||
// endregion
|
||||
}
|
||||
|
@ -42,8 +42,11 @@ import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersiste
|
||||
import org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentPropertyConverter;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
|
||||
import org.springframework.data.elasticsearch.core.query.Field;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.SeqNoPrimaryTerm;
|
||||
import org.springframework.data.elasticsearch.core.query.SourceFilter;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.PreferredConstructor;
|
||||
@ -1024,7 +1027,61 @@ public class MappingElasticsearchConverter
|
||||
|
||||
// region queries
|
||||
@Override
|
||||
public void updateCriteriaQuery(CriteriaQuery criteriaQuery, Class<?> domainClass) {
|
||||
public void updateQuery(Query query, @Nullable Class<?> domainClass) {
|
||||
|
||||
Assert.notNull(query, "query must not be null");
|
||||
|
||||
if (domainClass != null) {
|
||||
|
||||
updateFieldsAndSourceFilter(query, domainClass);
|
||||
|
||||
if (query instanceof CriteriaQuery) {
|
||||
updateCriteriaQuery((CriteriaQuery) query, domainClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFieldsAndSourceFilter(Query query, Class<?> domainClass) {
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(domainClass);
|
||||
|
||||
if (persistentEntity != null) {
|
||||
List<String> fields = query.getFields();
|
||||
|
||||
if (!fields.isEmpty()) {
|
||||
query.setFields(updateFieldNames(fields, persistentEntity));
|
||||
}
|
||||
|
||||
SourceFilter sourceFilter = query.getSourceFilter();
|
||||
|
||||
if (sourceFilter != null) {
|
||||
|
||||
String[] includes = null;
|
||||
String[] excludes = null;
|
||||
|
||||
if (sourceFilter.getIncludes() != null) {
|
||||
includes = updateFieldNames(Arrays.asList(sourceFilter.getIncludes()), persistentEntity)
|
||||
.toArray(new String[] {});
|
||||
}
|
||||
|
||||
if (sourceFilter.getExcludes() != null) {
|
||||
excludes = updateFieldNames(Arrays.asList(sourceFilter.getExcludes()), persistentEntity)
|
||||
.toArray(new String[] {});
|
||||
}
|
||||
|
||||
query.addSourceFilter(new FetchSourceFilter(includes, excludes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> updateFieldNames(List<String> fields, ElasticsearchPersistentEntity<?> persistentEntity) {
|
||||
return fields.stream().map(fieldName -> {
|
||||
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getPersistentProperty(fieldName);
|
||||
return persistentProperty != null ? persistentProperty.getFieldName() : fieldName;
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void updateCriteriaQuery(CriteriaQuery criteriaQuery, Class<?> domainClass) {
|
||||
|
||||
Assert.notNull(criteriaQuery, "criteriaQuery must not be null");
|
||||
Assert.notNull(domainClass, "domainClass must not be null");
|
||||
|
@ -96,6 +96,15 @@ abstract class AbstractQuery implements Query {
|
||||
return fields;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFields(List<String> fields) {
|
||||
|
||||
Assert.notNull(fields, "fields must not be null");
|
||||
|
||||
this.fields.clear();
|
||||
this.fields.addAll(fields);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSourceFilter(SourceFilter sourceFilter) {
|
||||
this.sourceFilter = sourceFilter;
|
||||
|
@ -103,6 +103,13 @@ public interface Query {
|
||||
*/
|
||||
List<String> getFields();
|
||||
|
||||
/**
|
||||
* Set fields to be returned as part of search request
|
||||
* @param fields must not be {@literal null}
|
||||
* @since 4.3
|
||||
*/
|
||||
void setFields(List<String> fields);
|
||||
|
||||
/**
|
||||
* Add source filter to be added as part of search request
|
||||
*
|
||||
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.skyscreamer.jsonassert.JSONAssert.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
@ -25,6 +24,7 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.json.JSONException;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
@ -44,6 +44,9 @@ import org.springframework.data.elasticsearch.core.geo.GeoJsonPoint;
|
||||
import org.springframework.data.elasticsearch.core.mapping.SimpleElasticsearchMappingContext;
|
||||
import org.springframework.data.elasticsearch.core.query.Criteria;
|
||||
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
|
||||
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
|
||||
import org.springframework.data.elasticsearch.core.query.Query;
|
||||
import org.springframework.data.elasticsearch.core.query.SourceFilter;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
@ -356,9 +359,7 @@ public class CriteriaQueryMappingUnitTests {
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
CriteriaQuery criteriaQuery = new CriteriaQuery(
|
||||
new Criteria("persons.birthDate").is(LocalDate.of(1999, 10, 3))
|
||||
);
|
||||
CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("persons.birthDate").is(LocalDate.of(1999, 10, 3)));
|
||||
mappingElasticsearchConverter.updateQuery(criteriaQuery, House.class);
|
||||
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
||||
|
||||
@ -389,9 +390,7 @@ public class CriteriaQueryMappingUnitTests {
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
CriteriaQuery criteriaQuery = new CriteriaQuery(
|
||||
new Criteria("persons.nickName.keyword").is("Foobar")
|
||||
);
|
||||
CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("persons.nickName.keyword").is("Foobar"));
|
||||
mappingElasticsearchConverter.updateQuery(criteriaQuery, House.class);
|
||||
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
||||
|
||||
@ -417,14 +416,33 @@ public class CriteriaQueryMappingUnitTests {
|
||||
" }\n" + //
|
||||
"}\n"; //
|
||||
|
||||
CriteriaQuery criteriaQuery = new CriteriaQuery(
|
||||
new Criteria("persons.birthDate").is(LocalDate.of(1999, 10, 3))
|
||||
);
|
||||
CriteriaQuery criteriaQuery = new CriteriaQuery(new Criteria("persons.birthDate").is(LocalDate.of(1999, 10, 3)));
|
||||
mappingElasticsearchConverter.updateQuery(criteriaQuery, ObjectWithPerson.class);
|
||||
String queryString = new CriteriaQueryProcessor().createQuery(criteriaQuery.getCriteria()).toString();
|
||||
|
||||
assertEquals(expected, queryString, false);
|
||||
}
|
||||
|
||||
@Test // #1778
|
||||
@DisplayName("should map names in source fields and SourceFilters")
|
||||
void shouldMapNamesInSourceFieldsAndSourceFilters() {
|
||||
|
||||
Query query = Query.findAll();
|
||||
// Note: we don't care if these filters make sense here, this test is only about name mapping
|
||||
query.addFields("firstName", "lastName");
|
||||
query.addSourceFilter(new FetchSourceFilter(new String[] { "firstName" }, new String[] { "lastName" }));
|
||||
|
||||
mappingElasticsearchConverter.updateQuery(query, Person.class);
|
||||
|
||||
SoftAssertions softly = new SoftAssertions();
|
||||
softly.assertThat(query.getFields()).containsExactly("first-name", "last-name");
|
||||
SourceFilter sourceFilter = query.getSourceFilter();
|
||||
softly.assertThat(sourceFilter).isNotNull();
|
||||
softly.assertThat(sourceFilter.getIncludes()).containsExactly("first-name");
|
||||
softly.assertThat(sourceFilter.getExcludes()).containsExactly("last-name");
|
||||
softly.assertAll();
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
// region helper functions
|
||||
@ -442,7 +460,8 @@ public class CriteriaQueryMappingUnitTests {
|
||||
@Nullable @Id String id;
|
||||
@Nullable @Field(name = "first-name") String firstName;
|
||||
@Nullable @Field(name = "last-name") String lastName;
|
||||
@Nullable @MultiField(mainField = @Field(name="nick-name"), otherFields = {@InnerField(suffix = "keyword", type = FieldType.Keyword)}) String nickName;
|
||||
@Nullable @MultiField(mainField = @Field(name = "nick-name"),
|
||||
otherFields = { @InnerField(suffix = "keyword", type = FieldType.Keyword) }) String nickName;
|
||||
@Nullable @Field(name = "created-date", type = FieldType.Date, format = DateFormat.epoch_millis) Date createdDate;
|
||||
@Nullable @Field(name = "birth-date", type = FieldType.Date, format = {},
|
||||
pattern = "dd.MM.uuuu") LocalDate birthDate;
|
||||
@ -450,16 +469,12 @@ public class CriteriaQueryMappingUnitTests {
|
||||
|
||||
static class House {
|
||||
@Nullable @Id String id;
|
||||
@Nullable
|
||||
@Field(name = "per-sons", type = FieldType.Nested)
|
||||
List<Person> persons;
|
||||
@Nullable @Field(name = "per-sons", type = FieldType.Nested) List<Person> persons;
|
||||
}
|
||||
|
||||
static class ObjectWithPerson {
|
||||
@Nullable @Id String id;
|
||||
@Nullable
|
||||
@Field(name = "per-sons", type = FieldType.Object)
|
||||
List<Person> persons;
|
||||
@Nullable @Field(name = "per-sons", type = FieldType.Object) List<Person> persons;
|
||||
}
|
||||
|
||||
static class GeoShapeEntity {
|
||||
|
Loading…
x
Reference in New Issue
Block a user