mirror of
				https://github.com/spring-projects/spring-data-elasticsearch.git
				synced 2025-10-30 22:28:47 +00:00 
			
		
		
		
	DATAES-462 - Add support for mapping max score and document scores.
Original pull request: #207.
This commit is contained in:
		
							parent
							
								
									112600261d
								
							
						
					
					
						commit
						d996406113
					
				| @ -0,0 +1,23 @@ | |||||||
|  | package org.springframework.data.elasticsearch.annotations; | ||||||
|  | 
 | ||||||
|  | import java.lang.annotation.Documented; | ||||||
|  | import java.lang.annotation.ElementType; | ||||||
|  | import java.lang.annotation.Inherited; | ||||||
|  | import java.lang.annotation.Retention; | ||||||
|  | import java.lang.annotation.RetentionPolicy; | ||||||
|  | import java.lang.annotation.Target; | ||||||
|  | 
 | ||||||
|  | import org.springframework.data.annotation.ReadOnlyProperty; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Specifies that this field is used for storing the document score. | ||||||
|  |  *  | ||||||
|  |  * @author Sascha Woo | ||||||
|  |  */ | ||||||
|  | @Retention(RetentionPolicy.RUNTIME) | ||||||
|  | @Target(ElementType.FIELD) | ||||||
|  | @Documented | ||||||
|  | @Inherited | ||||||
|  | @ReadOnlyProperty | ||||||
|  | public @interface Score { | ||||||
|  | } | ||||||
| @ -54,6 +54,7 @@ import com.fasterxml.jackson.core.JsonGenerator; | |||||||
|  * @author Chris White |  * @author Chris White | ||||||
|  * @author Mark Paluch |  * @author Mark Paluch | ||||||
|  * @author Ilkang Na |  * @author Ilkang Na | ||||||
|  |  * @author Sascha Woo | ||||||
|  */ |  */ | ||||||
| public class DefaultResultMapper extends AbstractResultMapper { | public class DefaultResultMapper extends AbstractResultMapper { | ||||||
| 
 | 
 | ||||||
| @ -82,6 +83,8 @@ public class DefaultResultMapper extends AbstractResultMapper { | |||||||
| 	@Override | 	@Override | ||||||
| 	public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) { | 	public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) { | ||||||
| 		long totalHits = response.getHits().getTotalHits(); | 		long totalHits = response.getHits().getTotalHits(); | ||||||
|  | 		float maxScore = response.getHits().getMaxScore(); | ||||||
|  | 
 | ||||||
| 		List<T> results = new ArrayList<>(); | 		List<T> results = new ArrayList<>(); | ||||||
| 		for (SearchHit hit : response.getHits()) { | 		for (SearchHit hit : response.getHits()) { | ||||||
| 			if (hit != null) { | 			if (hit != null) { | ||||||
| @ -91,14 +94,17 @@ public class DefaultResultMapper extends AbstractResultMapper { | |||||||
| 				} else { | 				} else { | ||||||
| 					result = mapEntity(hit.getFields().values(), clazz); | 					result = mapEntity(hit.getFields().values(), clazz); | ||||||
| 				} | 				} | ||||||
|  | 
 | ||||||
| 				setPersistentEntityId(result, hit.getId(), clazz); | 				setPersistentEntityId(result, hit.getId(), clazz); | ||||||
| 				setPersistentEntityVersion(result, hit.getVersion(), clazz); | 				setPersistentEntityVersion(result, hit.getVersion(), clazz); | ||||||
|  | 				setPersistentEntityScore(result, hit.getScore(), clazz); | ||||||
| 				populateScriptFields(result, hit); | 				populateScriptFields(result, hit); | ||||||
| 				results.add(result); | 				results.add(result); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|         return new AggregatedPageImpl<T>(results, pageable, totalHits, response.getAggregations(), response.getScrollId()); | 		return new AggregatedPageImpl<T>(results, pageable, totalHits, response.getAggregations(), response.getScrollId(), | ||||||
|  | 				maxScore); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private <T> void populateScriptFields(T result, SearchHit hit) { | 	private <T> void populateScriptFields(T result, SearchHit hit) { | ||||||
| @ -113,8 +119,8 @@ public class DefaultResultMapper extends AbstractResultMapper { | |||||||
| 						try { | 						try { | ||||||
| 							field.set(result, searchHitField.getValue()); | 							field.set(result, searchHitField.getValue()); | ||||||
| 						} catch (IllegalArgumentException e) { | 						} catch (IllegalArgumentException e) { | ||||||
| 							throw new ElasticsearchException("failed to set scripted field: " + name + " with value: " | 							throw new ElasticsearchException( | ||||||
| 									+ searchHitField.getValue(), e); | 									"failed to set scripted field: " + name + " with value: " + searchHitField.getValue(), e); | ||||||
| 						} catch (IllegalAccessException e) { | 						} catch (IllegalAccessException e) { | ||||||
| 							throw new ElasticsearchException("failed to access scripted field: " + name, e); | 							throw new ElasticsearchException("failed to access scripted field: " + name, e); | ||||||
| 						} | 						} | ||||||
| @ -178,9 +184,7 @@ public class DefaultResultMapper extends AbstractResultMapper { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) { | 	private <T> void setPersistentEntityId(T result, String id, Class<T> clazz) { | ||||||
| 
 |  | ||||||
| 		if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) { | 		if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) { | ||||||
| 
 |  | ||||||
| 			ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(clazz); | 			ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getRequiredPersistentEntity(clazz); | ||||||
| 			ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty(); | 			ElasticsearchPersistentProperty idProperty = persistentEntity.getIdProperty(); | ||||||
| 
 | 
 | ||||||
| @ -188,13 +192,11 @@ public class DefaultResultMapper extends AbstractResultMapper { | |||||||
| 			if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) { | 			if (idProperty != null && idProperty.getType().isAssignableFrom(String.class)) { | ||||||
| 				persistentEntity.getPropertyAccessor(result).setProperty(idProperty, id); | 				persistentEntity.getPropertyAccessor(result).setProperty(idProperty, id); | ||||||
| 			} | 			} | ||||||
| 
 |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	private <T> void setPersistentEntityVersion(T result, long version, Class<T> clazz) { | 	private <T> void setPersistentEntityVersion(T result, long version, Class<T> clazz) { | ||||||
| 		if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) { | 		if (mappingContext != null && clazz.isAnnotationPresent(Document.class)) { | ||||||
| 
 |  | ||||||
| 			ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz); | 			ElasticsearchPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(clazz); | ||||||
| 			ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty(); | 			ElasticsearchPersistentProperty versionProperty = persistentEntity.getVersionProperty(); | ||||||
| 
 | 
 | ||||||
| @ -207,4 +209,16 @@ 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); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -0,0 +1,16 @@ | |||||||
|  | 
 | ||||||
|  | package org.springframework.data.elasticsearch.core; | ||||||
|  | 
 | ||||||
|  | import org.springframework.data.domain.Page; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * A score-aware page gaining information about max score. | ||||||
|  |  *  | ||||||
|  |  * @param <T> | ||||||
|  |  * @author Sascha Woo | ||||||
|  |  */ | ||||||
|  | public interface ScoredPage<T> extends Page<T> { | ||||||
|  | 
 | ||||||
|  | 	float getMaxScore(); | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -3,12 +3,14 @@ package org.springframework.data.elasticsearch.core.aggregation; | |||||||
| import org.elasticsearch.search.aggregations.Aggregation; | import org.elasticsearch.search.aggregations.Aggregation; | ||||||
| import org.elasticsearch.search.aggregations.Aggregations; | import org.elasticsearch.search.aggregations.Aggregations; | ||||||
| import org.springframework.data.elasticsearch.core.FacetedPage; | import org.springframework.data.elasticsearch.core.FacetedPage; | ||||||
|  | import org.springframework.data.elasticsearch.core.ScoredPage; | ||||||
| import org.springframework.data.elasticsearch.core.ScrolledPage; | import org.springframework.data.elasticsearch.core.ScrolledPage; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * @author Petar Tahchiev |  * @author Petar Tahchiev | ||||||
|  |  * @author Sascha Woo | ||||||
|  */ |  */ | ||||||
| public interface AggregatedPage<T> extends FacetedPage<T>, ScrolledPage<T> { | public interface AggregatedPage<T> extends FacetedPage<T>, ScrolledPage<T>, ScoredPage<T> { | ||||||
| 
 | 
 | ||||||
| 	boolean hasAggregations(); | 	boolean hasAggregations(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -15,9 +15,7 @@ | |||||||
|  */ |  */ | ||||||
| package org.springframework.data.elasticsearch.core.aggregation.impl; | package org.springframework.data.elasticsearch.core.aggregation.impl; | ||||||
| 
 | 
 | ||||||
| import java.util.HashMap; |  | ||||||
| import java.util.List; | import java.util.List; | ||||||
| import java.util.Map; |  | ||||||
| 
 | 
 | ||||||
| import org.elasticsearch.search.aggregations.Aggregation; | import org.elasticsearch.search.aggregations.Aggregation; | ||||||
| import org.elasticsearch.search.aggregations.Aggregations; | import org.elasticsearch.search.aggregations.Aggregations; | ||||||
| @ -29,55 +27,77 @@ import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage; | |||||||
|  * @author Petar Tahchiev |  * @author Petar Tahchiev | ||||||
|  * @author Artur Konczak |  * @author Artur Konczak | ||||||
|  * @author Mohsin Husen |  * @author Mohsin Husen | ||||||
|  |  * @author Sascha Woo | ||||||
|  */ |  */ | ||||||
| public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements AggregatedPage<T> { | public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements AggregatedPage<T> { | ||||||
| 
 | 
 | ||||||
| 	private Aggregations aggregations; | 	private Aggregations aggregations; | ||||||
| 	private Map<String, Aggregation> mapOfAggregations = new HashMap<>(); | 	private String scrollId; | ||||||
|     private String scrollId; | 	private float maxScore; | ||||||
| 
 | 
 | ||||||
| 	public AggregatedPageImpl(List<T> content) { | 	public AggregatedPageImpl(List<T> content) { | ||||||
| 		super(content); | 		super(content); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public AggregatedPageImpl(List<T> content, float maxScore) { | ||||||
|  | 		super(content); | ||||||
|  | 		this.maxScore = maxScore; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public AggregatedPageImpl(List<T> content, String scrollId) { | 	public AggregatedPageImpl(List<T> content, String scrollId) { | ||||||
| 		super(content); | 		super(content); | ||||||
| 		this.scrollId = scrollId; | 		this.scrollId = scrollId; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public AggregatedPageImpl(List<T> content, String scrollId, float maxScore) { | ||||||
|  | 		this(content, scrollId); | ||||||
|  | 		this.maxScore = maxScore; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total) { | 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total) { | ||||||
| 		super(content, pageable, total); | 		super(content, pageable, total); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, float maxScore) { | ||||||
|  | 		super(content, pageable, total); | ||||||
|  | 		this.maxScore = maxScore; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, String scrollId) { | 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, String scrollId) { | ||||||
| 		super(content, pageable, total); | 		super(content, pageable, total); | ||||||
| 		this.scrollId = scrollId; | 		this.scrollId = scrollId; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, String scrollId, float maxScore) { | ||||||
|  | 		this(content, pageable, total, scrollId); | ||||||
|  | 		this.maxScore = maxScore; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations) { | 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations) { | ||||||
| 		super(content, pageable, total); | 		super(content, pageable, total); | ||||||
| 		this.aggregations = aggregations; | 		this.aggregations = aggregations; | ||||||
| 		if (aggregations != null) { |  | ||||||
| 			for (Aggregation aggregation : aggregations) { |  | ||||||
| 				mapOfAggregations.put(aggregation.getName(), aggregation); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations, String scrollId) { | 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations, float maxScore) { | ||||||
| 		super(content, pageable, total); | 		this(content, pageable, total, aggregations); | ||||||
| 		this.aggregations = aggregations; | 		this.maxScore = maxScore; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations, | ||||||
|  | 			String scrollId) { | ||||||
|  | 		this(content, pageable, total, aggregations); | ||||||
| 		this.scrollId = scrollId; | 		this.scrollId = scrollId; | ||||||
| 		if (aggregations != null) { | 	} | ||||||
| 			for (Aggregation aggregation : aggregations) { | 
 | ||||||
| 				mapOfAggregations.put(aggregation.getName(), aggregation); | 	public AggregatedPageImpl(List<T> content, Pageable pageable, long total, Aggregations aggregations, String scrollId, | ||||||
| 			} | 			float maxScore) { | ||||||
| 		} | 		this(content, pageable, total, aggregations, scrollId); | ||||||
|  | 		this.maxScore = maxScore; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public boolean hasAggregations() { | 	public boolean hasAggregations() { | ||||||
| 		return aggregations != null && mapOfAggregations.size() > 0; | 		return aggregations != null; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| @ -94,4 +114,9 @@ public class AggregatedPageImpl<T> extends FacetedPageImpl<T> implements Aggrega | |||||||
| 	public String getScrollId() { | 	public String getScrollId() { | ||||||
| 		return scrollId; | 		return scrollId; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public float getMaxScore() { | ||||||
|  | 		return maxScore; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ | |||||||
| package org.springframework.data.elasticsearch.core.mapping; | package org.springframework.data.elasticsearch.core.mapping; | ||||||
| 
 | 
 | ||||||
| import org.springframework.data.mapping.PersistentEntity; | import org.springframework.data.mapping.PersistentEntity; | ||||||
|  | import org.springframework.lang.Nullable; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * ElasticsearchPersistentEntity |  * ElasticsearchPersistentEntity | ||||||
| @ -23,6 +24,7 @@ import org.springframework.data.mapping.PersistentEntity; | |||||||
|  * @author Rizwan Idrees |  * @author Rizwan Idrees | ||||||
|  * @author Mohsin Husen |  * @author Mohsin Husen | ||||||
|  * @author Mark Paluch |  * @author Mark Paluch | ||||||
|  |  * @author Sascha Woo | ||||||
|  */ |  */ | ||||||
| public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, ElasticsearchPersistentProperty> { | public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, ElasticsearchPersistentProperty> { | ||||||
| 
 | 
 | ||||||
| @ -49,4 +51,22 @@ public interface ElasticsearchPersistentEntity<T> extends PersistentEntity<T, El | |||||||
| 	String settingPath(); | 	String settingPath(); | ||||||
| 
 | 
 | ||||||
| 	boolean isCreateIndexAndMapping(); | 	boolean isCreateIndexAndMapping(); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Returns whether the {@link ElasticsearchPersistentEntity} has an score property. If this call returns | ||||||
|  | 	 * {@literal true}, {@link #getScoreProperty()} will return a non-{@literal null} value. | ||||||
|  | 	 * | ||||||
|  | 	 * @return false when {@link ElasticsearchPersistentEntity} does not define a score property. | ||||||
|  | 	 */ | ||||||
|  | 	boolean hasScoreProperty(); | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the score property of the {@link ElasticsearchPersistentEntity}. Can be {@literal null} in case no score | ||||||
|  | 	 * property is available on the entity. | ||||||
|  | 	 * | ||||||
|  | 	 * @return the score {@link ElasticsearchPersistentProperty} of the {@link PersistentEntity} or {@literal null} if not | ||||||
|  | 	 *         defined. | ||||||
|  | 	 */ | ||||||
|  | 	@Nullable | ||||||
|  | 	ElasticsearchPersistentProperty getScoreProperty(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -23,12 +23,24 @@ import org.springframework.data.mapping.PersistentProperty; | |||||||
|  * |  * | ||||||
|  * @author Rizwan Idrees |  * @author Rizwan Idrees | ||||||
|  * @author Mohsin Husen |  * @author Mohsin Husen | ||||||
|  |  * @author Sascha Woo | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| public interface ElasticsearchPersistentProperty extends PersistentProperty<ElasticsearchPersistentProperty> { | public interface ElasticsearchPersistentProperty extends PersistentProperty<ElasticsearchPersistentProperty> { | ||||||
| 
 | 
 | ||||||
| 	String getFieldName(); | 	String getFieldName(); | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Returns whether the current property is a <em>potential</em> score property of the owning | ||||||
|  | 	 * {@link ElasticsearchPersistentEntity}. This method is mainly used by {@link ElasticsearchPersistentEntity} | ||||||
|  | 	 * implementation to discover score property candidates on {@link ElasticsearchPersistentEntity} creation you should | ||||||
|  | 	 * rather call {@link ElasticsearchPersistentEntity#isScoreProperty(PersistentProperty)} to determine whether the | ||||||
|  | 	 * current property is the version property of that {@link ElasticsearchPersistentEntity} under consideration. | ||||||
|  | 	 * | ||||||
|  | 	 * @return | ||||||
|  | 	 */ | ||||||
|  | 	boolean isScoreProperty(); | ||||||
|  | 
 | ||||||
| 	public enum PropertyToFieldNameConverter implements Converter<ElasticsearchPersistentProperty, String> { | 	public enum PropertyToFieldNameConverter implements Converter<ElasticsearchPersistentProperty, String> { | ||||||
| 
 | 
 | ||||||
| 		INSTANCE; | 		INSTANCE; | ||||||
|  | |||||||
| @ -18,7 +18,6 @@ package org.springframework.data.elasticsearch.core.mapping; | |||||||
| import static org.springframework.util.StringUtils.*; | import static org.springframework.util.StringUtils.*; | ||||||
| 
 | 
 | ||||||
| import java.util.Locale; | import java.util.Locale; | ||||||
| import java.util.Optional; |  | ||||||
| 
 | 
 | ||||||
| import org.springframework.beans.BeansException; | import org.springframework.beans.BeansException; | ||||||
| import org.springframework.context.ApplicationContext; | import org.springframework.context.ApplicationContext; | ||||||
| @ -28,12 +27,14 @@ import org.springframework.context.expression.BeanFactoryResolver; | |||||||
| import org.springframework.data.elasticsearch.annotations.Document; | import org.springframework.data.elasticsearch.annotations.Document; | ||||||
| import org.springframework.data.elasticsearch.annotations.Parent; | import org.springframework.data.elasticsearch.annotations.Parent; | ||||||
| import org.springframework.data.elasticsearch.annotations.Setting; | import org.springframework.data.elasticsearch.annotations.Setting; | ||||||
|  | import org.springframework.data.mapping.MappingException; | ||||||
| import org.springframework.data.mapping.model.BasicPersistentEntity; | import org.springframework.data.mapping.model.BasicPersistentEntity; | ||||||
| import org.springframework.data.util.TypeInformation; | import org.springframework.data.util.TypeInformation; | ||||||
| import org.springframework.expression.Expression; | import org.springframework.expression.Expression; | ||||||
| import org.springframework.expression.ParserContext; | import org.springframework.expression.ParserContext; | ||||||
| import org.springframework.expression.spel.standard.SpelExpressionParser; | import org.springframework.expression.spel.standard.SpelExpressionParser; | ||||||
| import org.springframework.expression.spel.support.StandardEvaluationContext; | import org.springframework.expression.spel.support.StandardEvaluationContext; | ||||||
|  | import org.springframework.lang.Nullable; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -43,6 +44,7 @@ import org.springframework.util.Assert; | |||||||
|  * @author Rizwan Idrees |  * @author Rizwan Idrees | ||||||
|  * @author Mohsin Husen |  * @author Mohsin Husen | ||||||
|  * @author Mark Paluch |  * @author Mark Paluch | ||||||
|  |  * @author Sascha Woo | ||||||
|  */ |  */ | ||||||
| public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntity<T, ElasticsearchPersistentProperty> | public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntity<T, ElasticsearchPersistentProperty> | ||||||
| 		implements ElasticsearchPersistentEntity<T>, ApplicationContextAware { | 		implements ElasticsearchPersistentEntity<T>, ApplicationContextAware { | ||||||
| @ -59,6 +61,7 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit | |||||||
| 	private String indexStoreType; | 	private String indexStoreType; | ||||||
| 	private String parentType; | 	private String parentType; | ||||||
| 	private ElasticsearchPersistentProperty parentIdProperty; | 	private ElasticsearchPersistentProperty parentIdProperty; | ||||||
|  | 	private ElasticsearchPersistentProperty scoreProperty; | ||||||
| 	private String settingPath; | 	private String settingPath; | ||||||
| 	private boolean createIndexAndMapping; | 	private boolean createIndexAndMapping; | ||||||
| 
 | 
 | ||||||
| @ -150,6 +153,17 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit | |||||||
| 		return createIndexAndMapping; | 		return createIndexAndMapping; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean hasScoreProperty() { | ||||||
|  | 		return scoreProperty != null; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	@Nullable | ||||||
|  | 	@Override | ||||||
|  | 	public ElasticsearchPersistentProperty getScoreProperty() { | ||||||
|  | 		return scoreProperty; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public void addPersistentProperty(ElasticsearchPersistentProperty property) { | 	public void addPersistentProperty(ElasticsearchPersistentProperty property) { | ||||||
| 		super.addPersistentProperty(property); | 		super.addPersistentProperty(property); | ||||||
| @ -165,7 +179,21 @@ public class SimpleElasticsearchPersistentEntity<T> extends BasicPersistentEntit | |||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (property.isVersionProperty()) { | 		if (property.isVersionProperty()) { | ||||||
| 			Assert.isTrue(property.getType() == Long.class, "Version property should be Long"); | 			Assert.isTrue(property.getType() == Long.class, "Version property must be of type Long!"); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (property.isScoreProperty()) { | ||||||
|  | 			ElasticsearchPersistentProperty scoreProperty = this.scoreProperty; | ||||||
|  | 
 | ||||||
|  | 			if (scoreProperty != null) { | ||||||
|  | 				throw new MappingException( | ||||||
|  | 						String.format("Attempt to add score property %s but already have property %s registered " | ||||||
|  | 								+ "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; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,11 +18,13 @@ package org.springframework.data.elasticsearch.core.mapping; | |||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
| import java.util.Set; | import java.util.Set; | ||||||
| 
 | 
 | ||||||
|  | import org.springframework.data.elasticsearch.annotations.Score; | ||||||
| import org.springframework.data.mapping.Association; | import org.springframework.data.mapping.Association; | ||||||
| import org.springframework.data.mapping.PersistentEntity; | import org.springframework.data.mapping.PersistentEntity; | ||||||
| import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; | import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty; | ||||||
| import org.springframework.data.mapping.model.Property; | import org.springframework.data.mapping.model.Property; | ||||||
| import org.springframework.data.mapping.model.SimpleTypeHolder; | import org.springframework.data.mapping.model.SimpleTypeHolder; | ||||||
|  | import org.springframework.data.util.Lazy; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Elasticsearch specific {@link org.springframework.data.mapping.PersistentProperty} implementation processing |  * Elasticsearch specific {@link org.springframework.data.mapping.PersistentProperty} implementation processing | ||||||
| @ -30,12 +32,15 @@ import org.springframework.data.mapping.model.SimpleTypeHolder; | |||||||
|  * @author Rizwan Idrees |  * @author Rizwan Idrees | ||||||
|  * @author Mohsin Husen |  * @author Mohsin Husen | ||||||
|  * @author Mark Paluch |  * @author Mark Paluch | ||||||
|  |  * @author Sascha Woo | ||||||
|  */ |  */ | ||||||
| public class SimpleElasticsearchPersistentProperty extends | public class SimpleElasticsearchPersistentProperty extends | ||||||
| 		AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty { | 		AnnotationBasedPersistentProperty<ElasticsearchPersistentProperty> implements ElasticsearchPersistentProperty { | ||||||
| 
 | 
 | ||||||
| 	private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<>(); | 	private static final Set<Class<?>> SUPPORTED_ID_TYPES = new HashSet<>(); | ||||||
| 	private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<>(); | 	private static final Set<String> SUPPORTED_ID_PROPERTY_NAMES = new HashSet<>(); | ||||||
|  | 	 | ||||||
|  | 	private final Lazy<Boolean> isScore = Lazy.of(() -> isAnnotationPresent(Score.class)); | ||||||
| 
 | 
 | ||||||
| 	static { | 	static { | ||||||
| 		SUPPORTED_ID_TYPES.add(String.class); | 		SUPPORTED_ID_TYPES.add(String.class); | ||||||
| @ -62,4 +67,9 @@ public class SimpleElasticsearchPersistentProperty extends | |||||||
| 	protected Association<ElasticsearchPersistentProperty> createAssociation() { | 	protected Association<ElasticsearchPersistentProperty> createAssociation() { | ||||||
| 		return null; | 		return null; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	@Override | ||||||
|  | 	public boolean isScoreProperty() { | ||||||
|  | 		return isScore.get(); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -36,6 +36,8 @@ import org.elasticsearch.search.SearchHit; | |||||||
| import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; | import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder; | ||||||
| import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; | import org.elasticsearch.search.fetch.subphase.highlight.HighlightField; | ||||||
| import org.elasticsearch.search.sort.FieldSortBuilder; | 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.elasticsearch.search.sort.SortOrder; | ||||||
| import org.hamcrest.Matchers; | import org.hamcrest.Matchers; | ||||||
| import org.junit.Before; | import org.junit.Before; | ||||||
| @ -1512,6 +1514,31 @@ public class ElasticsearchTemplateTests { | |||||||
| 		assertThat(page.getContent().get(0).getMessage(), is("ab")); | 		assertThat(page.getContent().get(0).getMessage(), is("ab")); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	@Test // DATAES-462 | ||||||
|  | 	public void shouldReturnScores() { | ||||||
|  | 		// given | ||||||
|  | 		List<IndexQuery> indexQueries = new ArrayList<>(); | ||||||
|  | 
 | ||||||
|  | 		indexQueries.add(buildIndex(SampleEntity.builder().id("1").message("ab xz").build())); | ||||||
|  | 		indexQueries.add(buildIndex(SampleEntity.builder().id("2").message("bc").build())); | ||||||
|  | 		indexQueries.add(buildIndex(SampleEntity.builder().id("3").message("ac xz hi").build())); | ||||||
|  | 
 | ||||||
|  | 		elasticsearchTemplate.bulkIndex(indexQueries); | ||||||
|  | 		elasticsearchTemplate.refresh(SampleEntity.class); | ||||||
|  | 
 | ||||||
|  | 		// when | ||||||
|  | 		SearchQuery searchQuery = new NativeSearchQueryBuilder() | ||||||
|  | 				.withQuery(termQuery("message", "xz")) | ||||||
|  | 				.withSort(SortBuilders.fieldSort("message")) | ||||||
|  | 				.withTrackScores(true) | ||||||
|  | 				.build(); | ||||||
|  | 
 | ||||||
|  | 		AggregatedPage<SampleEntity> page = elasticsearchTemplate.queryForPage(searchQuery, SampleEntity.class); | ||||||
|  | 
 | ||||||
|  | 		// then | ||||||
|  | 		assertThat(page.getMaxScore(), greaterThan(0f)); | ||||||
|  | 		assertThat(page.getContent().get(0).getScore(), greaterThan(0f)); | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| 	public void shouldDoIndexWithoutId() { | 	public void shouldDoIndexWithoutId() { | ||||||
|  | |||||||
| @ -15,29 +15,29 @@ | |||||||
|  */ |  */ | ||||||
| package org.springframework.data.elasticsearch.entities; | package org.springframework.data.elasticsearch.entities; | ||||||
| 
 | 
 | ||||||
| import java.lang.Double; | import static org.springframework.data.elasticsearch.annotations.FieldType.*; | ||||||
| import java.lang.Long; | 
 | ||||||
| import java.lang.Object; |  | ||||||
| import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||||
| import lombok.Builder; | import lombok.Builder; | ||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
| import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||||
| import lombok.Setter; | import lombok.Setter; | ||||||
| import lombok.ToString; | import lombok.ToString; | ||||||
|  | 
 | ||||||
| import org.springframework.data.annotation.Id; | import org.springframework.data.annotation.Id; | ||||||
| import org.springframework.data.annotation.Version; | import org.springframework.data.annotation.Version; | ||||||
| import org.springframework.data.elasticsearch.annotations.Document; | import org.springframework.data.elasticsearch.annotations.Document; | ||||||
| import org.springframework.data.elasticsearch.annotations.Field; | import org.springframework.data.elasticsearch.annotations.Field; | ||||||
|  | import org.springframework.data.elasticsearch.annotations.Score; | ||||||
| import org.springframework.data.elasticsearch.annotations.ScriptedField; | import org.springframework.data.elasticsearch.annotations.ScriptedField; | ||||||
| import org.springframework.data.elasticsearch.core.geo.GeoPoint; | import org.springframework.data.elasticsearch.core.geo.GeoPoint; | ||||||
| import static org.springframework.data.elasticsearch.annotations.FieldType.*; |  | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * @author Rizwan Idrees |  * @author Rizwan Idrees | ||||||
|  * @author Mohsin Husen |  * @author Mohsin Husen | ||||||
|  * @author Chris White |  * @author Chris White | ||||||
|  |  * @author Sascha Woo | ||||||
|  */ |  */ | ||||||
| 
 |  | ||||||
| @Setter | @Setter | ||||||
| @Getter | @Getter | ||||||
| @NoArgsConstructor | @NoArgsConstructor | ||||||
| @ -58,11 +58,11 @@ public class SampleEntity { | |||||||
| 	private Double scriptedRate; | 	private Double scriptedRate; | ||||||
| 	private boolean available; | 	private boolean available; | ||||||
| 	private String highlightedMessage; | 	private String highlightedMessage; | ||||||
| 
 |  | ||||||
| 	private GeoPoint location; | 	private GeoPoint location; | ||||||
| 
 |  | ||||||
| 	@Version | 	@Version | ||||||
| 	private Long version; | 	private Long version; | ||||||
|  | 	@Score | ||||||
|  | 	private float score; | ||||||
| 
 | 
 | ||||||
| 	@Override | 	@Override | ||||||
| 	public boolean equals(Object o) { | 	public boolean equals(Object o) { | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user