mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-06-24 21:12:12 +00:00
DATAES-462 - Polishing.
SimpleElasticsearchPersistentProperty now already checks for the correct type of score properties. Added unit tests for that. Also added unit tests for SimpleElasticsearchPersistentEntity rejecting more than one score property being present. Additional non-null assertions on components that are required so that we can remove superfluous null checks. A bit o formatting, Javadoc, missing @since tags and license headers. Original pull request: #207.
This commit is contained in:
parent
d996406113
commit
5ddb46c435
@ -13,11 +13,11 @@ import org.springframework.data.annotation.ReadOnlyProperty;
|
||||
* Specifies that this field is used for storing the document score.
|
||||
*
|
||||
* @author Sascha Woo
|
||||
* @since 3.1
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
@Documented
|
||||
@Inherited
|
||||
@ReadOnlyProperty
|
||||
public @interface Score {
|
||||
}
|
||||
public @interface Score {}
|
||||
|
@ -20,6 +20,7 @@ import static org.apache.commons.lang.StringUtils.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.data.elasticsearch.ElasticsearchException;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Artur Konczak
|
||||
@ -29,6 +30,9 @@ public abstract class AbstractResultMapper implements ResultsMapper {
|
||||
private EntityMapper entityMapper;
|
||||
|
||||
public AbstractResultMapper(EntityMapper entityMapper) {
|
||||
|
||||
Assert.notNull(entityMapper, "EntityMapper must not be null!");
|
||||
|
||||
this.entityMapper = entityMapper;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2014-2017 the original author or authors.
|
||||
* Copyright 2014-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -58,30 +58,39 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
||||
*/
|
||||
public class DefaultResultMapper extends AbstractResultMapper {
|
||||
|
||||
private MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
|
||||
private final MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext;
|
||||
|
||||
public DefaultResultMapper() {
|
||||
this(new SimpleElasticsearchMappingContext());
|
||||
}
|
||||
|
||||
public DefaultResultMapper(MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext) {
|
||||
|
||||
super(new DefaultEntityMapper(mappingContext));
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
public DefaultResultMapper(EntityMapper entityMapper) {
|
||||
super(entityMapper);
|
||||
this(new SimpleElasticsearchMappingContext(), entityMapper);
|
||||
}
|
||||
|
||||
public DefaultResultMapper(
|
||||
MappingContext<? extends ElasticsearchPersistentEntity<?>, ElasticsearchPersistentProperty> mappingContext,
|
||||
EntityMapper entityMapper) {
|
||||
|
||||
super(entityMapper);
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
|
||||
|
||||
long totalHits = response.getHits().getTotalHits();
|
||||
float maxScore = response.getHits().getMaxScore();
|
||||
|
||||
@ -98,6 +107,7 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
setPersistentEntityId(result, hit.getId(), clazz);
|
||||
setPersistentEntityVersion(result, hit.getVersion(), clazz);
|
||||
setPersistentEntityScore(result, hit.getScore(), clazz);
|
||||
|
||||
populateScriptFields(result, hit);
|
||||
results.add(result);
|
||||
}
|
||||
@ -184,7 +194,9 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
}
|
||||
|
||||
private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) {
|
||||
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
|
||||
|
||||
if (clazz.isAnnotationPresent(Document.class)) {
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(clazz);
|
||||
ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty();
|
||||
|
||||
@ -196,7 +208,9 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
}
|
||||
|
||||
private <T> void setPersistentEntityVersion(T result, long version, Class<T> clazz) {
|
||||
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
|
||||
|
||||
if (clazz.isAnnotationPresent(Document.class)) {
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz);
|
||||
ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
|
||||
@ -211,14 +225,17 @@ public class DefaultResultMapper extends AbstractResultMapper {
|
||||
}
|
||||
|
||||
private <T> void setPersistentEntityScore(T result, float score, Class<T> clazz) {
|
||||
if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) {
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(clazz);
|
||||
ElasticsearchPersistentProperty scoreProperty = persistentEntity.getScoreProperty();
|
||||
Class<?> type = scoreProperty.getType();
|
||||
|
||||
if (scoreProperty != null && (type == Float.class || type == Float.TYPE)) {
|
||||
persistentEntity.getPropertyAccessor(result).setProperty(scoreProperty, score);
|
||||
if (clazz.isAnnotationPresent(Document.class)) {
|
||||
|
||||
ElasticsearchPersistentEntity<?> entity = mappingContext.getRequiredPersistentEntity(clazz);
|
||||
|
||||
if (!entity.hasScoreProperty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
entity.getPropertyAccessor(result) //
|
||||
.setProperty(entity.getScoreProperty(), score);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,18 @@
|
||||
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
@ -12,5 +26,4 @@ import org.springframework.data.domain.Page;
|
||||
public interface ScoredPage<T> extends Page<T> {
|
||||
|
||||
float getMaxScore();
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -25,6 +25,7 @@ import org.springframework.lang.Nullable;
|
||||
* @author Mohsin Husen
|
||||
* @author Mark Paluch
|
||||
* @author Sascha Woo
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, ElasticsearchPersistentProperty> {
|
||||
|
||||
@ -57,6 +58,7 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
|
||||
* {@literal true}, {@link #getScoreProperty()} will return a non-{@literal null} value.
|
||||
*
|
||||
* @return false when {@link ElasticsearchPersistentEntity} does not define a score property.
|
||||
* @since 3.1
|
||||
*/
|
||||
boolean hasScoreProperty();
|
||||
|
||||
@ -66,6 +68,7 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El
|
||||
*
|
||||
* @return the score {@link ElasticsearchPersistentProperty} of the {@link PersistentEntity} or {@literal null} if not
|
||||
* defined.
|
||||
* @since 3.1
|
||||
*/
|
||||
@Nullable
|
||||
ElasticsearchPersistentProperty getScoreProperty();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -24,8 +24,8 @@ import org.springframework.data.mapping.PersistentProperty;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Sascha Woo
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
|
||||
public interface ElasticsearchPersistentProperty extends PersistentProperty<ElasticsearchPersistentProperty> {
|
||||
|
||||
String getFieldName();
|
||||
@ -38,6 +38,7 @@ public interface ElasticsearchPersistentProperty extends PersistentProperty<Elas
|
||||
* current property is the version property of that {@link ElasticsearchPersistentEntity} under consideration.
|
||||
*
|
||||
* @return
|
||||
* @since 3.1
|
||||
*/
|
||||
boolean isScoreProperty();
|
||||
|
||||
|
@ -183,6 +183,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
}
|
||||
|
||||
if (property.isScoreProperty()) {
|
||||
|
||||
ElasticsearchPersistentProperty scoreProperty = this.scoreProperty;
|
||||
|
||||
if (scoreProperty != null) {
|
||||
@ -191,8 +192,6 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit
|
||||
+ "as version. Check your mapping configuration!", property.getField(), scoreProperty.getField()));
|
||||
}
|
||||
|
||||
Assert.isTrue(property.getType() == Float.class || property.getType() == Float.TYPE, "Score property must be of type float!");
|
||||
|
||||
this.scoreProperty = property;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -15,16 +15,17 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.mapping;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.elasticsearch.annotations.Score;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.Lazy;
|
||||
|
||||
/**
|
||||
* Elasticsearch specific {@link org.springframework.data.mapping.PersistentProperty} implementation processing
|
||||
@ -33,6 +34,7 @@ import org.springframework.data.util.Lazy;
|
||||
* @author Mohsin Husen
|
||||
* @author Mark Paluch
|
||||
* @author Sascha Woo
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SimpleElasticsearchPersistentProperty extends
|
||||
AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty {
|
||||
@ -40,7 +42,7 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<>();
|
||||
private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<>();
|
||||
|
||||
private final Lazy<Boolean> isScore = Lazy.of(() -> isAnnotationPresent(Score.class));
|
||||
private final boolean isScore;
|
||||
|
||||
static {
|
||||
SUPPORTED_ID_TYPES.add(String.class);
|
||||
@ -50,7 +52,14 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
|
||||
public SimpleElasticsearchPersistentProperty(Property property,
|
||||
PersistentEntity<?, ElasticsearchPersistentProperty> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
super(property, owner, simpleTypeHolder);
|
||||
|
||||
this.isScore = isAnnotationPresent(Score.class);
|
||||
|
||||
if (isScore && !Arrays.asList(Float.TYPE, Float.class).contains(getType())) {
|
||||
throw new MappingException(String.format("Score property %s must be either of type float or Float!", property.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -68,8 +77,12 @@ public class SimpleElasticsearchPersistentProperty extends
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.mapping.ElasticsearchPersistentProperty#isScoreProperty()
|
||||
*/
|
||||
@Override
|
||||
public boolean isScoreProperty() {
|
||||
return isScore.get();
|
||||
return isScore;
|
||||
}
|
||||
}
|
||||
|
@ -165,11 +165,21 @@ abstract class AbstractQuery implements Query {
|
||||
this.indicesOptions = indicesOptions;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.elasticsearch.core.query.Query#getTrackScores()
|
||||
*/
|
||||
@Override
|
||||
public boolean getTrackScores() {
|
||||
return trackScores;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures whether to track scores.
|
||||
*
|
||||
* @param trackScores
|
||||
* @since 3.1
|
||||
*/
|
||||
public void setTrackScores(boolean trackScores) {
|
||||
this.trackScores = trackScores;
|
||||
}
|
||||
|
@ -130,6 +130,11 @@ public class NativeSearchQueryBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trackScores whether to track scores.
|
||||
* @return
|
||||
* @since 3.1
|
||||
*/
|
||||
public NativeSearchQueryBuilder withTrackScores(boolean trackScores) {
|
||||
this.trackScores = trackScores;
|
||||
return this;
|
||||
|
@ -132,6 +132,7 @@ public interface Query {
|
||||
* Get if scores will be computed and tracked, regardless of whether sorting on a field. Defaults to <tt>false</tt>.
|
||||
*
|
||||
* @return
|
||||
* @since 3.1
|
||||
*/
|
||||
boolean getTrackScores();
|
||||
|
||||
|
@ -46,6 +46,7 @@ import org.springframework.data.elasticsearch.entities.Car;
|
||||
import org.springframework.data.elasticsearch.entities.SampleEntity;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
@ -36,7 +36,6 @@ import org.elasticsearch.search.SearchHit;
|
||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
|
||||
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
|
||||
import org.elasticsearch.search.sort.FieldSortBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilder;
|
||||
import org.elasticsearch.search.sort.SortBuilders;
|
||||
import org.elasticsearch.search.sort.SortOrder;
|
||||
import org.hamcrest.Matchers;
|
||||
@ -1516,6 +1515,7 @@ public class ElasticsearchTemplateTests {
|
||||
|
||||
@Test // DATAES-462
|
||||
public void shouldReturnScores() {
|
||||
|
||||
// given
|
||||
List<IndexQuery> indexQueries = new ArrayList<>();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2017 the original author or authors.
|
||||
* Copyright 2013-2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -15,10 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.mapping;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.beans.IntrospectionException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.annotation.Version;
|
||||
import org.springframework.data.elasticsearch.annotations.Score;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
import org.springframework.data.mapping.model.Property;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
@ -30,6 +33,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Rizwan Idrees
|
||||
* @author Mohsin Husen
|
||||
* @author Mark Paluch
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SimpleElasticsearchPersistentEntityTests {
|
||||
|
||||
@ -62,6 +66,17 @@ public class SimpleElasticsearchPersistentEntityTests {
|
||||
// when
|
||||
entity.addPersistentProperty(persistentProperty2);
|
||||
}
|
||||
|
||||
@Test // DATAES-462
|
||||
public void rejectsMultipleScoreProperties() {
|
||||
|
||||
SimpleElasticsearchMappingContext context = new SimpleElasticsearchMappingContext();
|
||||
|
||||
assertThatExceptionOfType(MappingException.class) //
|
||||
.isThrownBy(() -> context.getRequiredPersistentEntity(TwoScoreProperties.class)) //
|
||||
.withMessageContaining("first") //
|
||||
.withMessageContaining("second");
|
||||
}
|
||||
|
||||
private static SimpleElasticsearchPersistentProperty createProperty(SimpleElasticsearchPersistentEntity<?> entity,
|
||||
String field) {
|
||||
@ -106,4 +121,12 @@ public class SimpleElasticsearchPersistentEntityTests {
|
||||
this.version2 = version2;
|
||||
}
|
||||
}
|
||||
|
||||
// DATAES-462
|
||||
|
||||
static class TwoScoreProperties {
|
||||
|
||||
@Score float first;
|
||||
@Score float second;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2018 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.mapping;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.elasticsearch.annotations.Score;
|
||||
import org.springframework.data.mapping.MappingException;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link SimpleElasticsearchPersistentProperty}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class SimpleElasticsearchPersistentPropertyUnitTests {
|
||||
|
||||
@Test // DATAES-462
|
||||
public void rejectsScorePropertyOfTypeOtherthanFloat() {
|
||||
|
||||
SimpleElasticsearchMappingContext context = new SimpleElasticsearchMappingContext();
|
||||
|
||||
assertThatExceptionOfType(MappingException.class) //
|
||||
.isThrownBy(() -> context.getRequiredPersistentEntity(InvalidScoreProperty.class)) //
|
||||
.withMessageContaining("scoreProperty");
|
||||
}
|
||||
|
||||
static class InvalidScoreProperty {
|
||||
@Score String scoreProperty;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user