mirror of
https://github.com/spring-projects/spring-data-elasticsearch.git
synced 2025-07-03 17:22:10 +00:00
parent
44a79093ce
commit
df5fd0b97c
@ -53,7 +53,7 @@ interface BookRepository extends Repository<Book, String> {
|
||||
@HighlightField(name = "name"),
|
||||
@HighlightField(name = "summary")
|
||||
})
|
||||
List<SearchHit<Book>> findByNameOrSummary(String text, String summary);
|
||||
SearchHits<Book> findByNameOrSummary(String text, String summary);
|
||||
}
|
||||
----
|
||||
====
|
||||
@ -62,6 +62,30 @@ It is possible to define multiple fields to be highlighted like above, and both
|
||||
|
||||
In the search results the highlight data can be retrieved from the `SearchHit` class.
|
||||
|
||||
=== @SourceFilters
|
||||
|
||||
Sometimes the user does not need to have all the properties of an entity returned from a search but only a subset.
|
||||
Elasticsearch provides source filtering to reduce the amount of data that is transferred across the network to the
|
||||
application.
|
||||
|
||||
When working with `Query` implementations and the `ElasticsearchOperations` this is easily possible by setting a
|
||||
source filter on the query.
|
||||
|
||||
When using repository methods there is the `@SourceFilters` annotation:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
interface BookRepository extends Repository<Book, String> {
|
||||
|
||||
@SourceFilters(includes = "name")
|
||||
SearchHits<Book> findByName(String text);
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
In this example, all the properties of the returned `Book` objects would be `null` except the name.
|
||||
|
||||
[[elasticsearch.annotation]]
|
||||
== Annotation based configuration
|
||||
|
||||
|
@ -16,11 +16,11 @@
|
||||
package org.springframework.data.elasticsearch.annotations;
|
||||
|
||||
/**
|
||||
* Values based on reference doc - https://www.elastic.co/guide/reference/mapping/date-format/. The patterns are taken
|
||||
* from this documentation and slightly adapted so that a Java {@link java.time.format.DateTimeFormatter} produces the
|
||||
* same values as the Elasticsearch formatter. Use <code>format = {}</code> to disable built-in date * formats in
|
||||
* the @Field annotation. If you want to use only a custom date format pattern, you must set the <code>format</code> *
|
||||
* property to empty <code>{}</code>.
|
||||
* Values based on <a href="https://www.elastic.co/guide/reference/mapping/date-format/">Elasticsearch reference
|
||||
* documentation</a>. The patterns are taken from this documentation and slightly adapted so that a Java
|
||||
* {@link java.time.format.DateTimeFormatter} produces the same values as the Elasticsearch formatter. Use
|
||||
* <code>format = {}</code> to disable built-in date formats in the {@link Field} annotation. If you want to use only a
|
||||
* custom date format pattern, you must set the <code>format</code> property to empty <code>{}</code>.
|
||||
*
|
||||
* @author Jakub Vavrik
|
||||
* @author Tim te Beek
|
||||
@ -49,7 +49,7 @@ public enum DateFormat {
|
||||
date_hour_minute_second_millis("uuuu-MM-dd'T'HH:mm:ss.SSS"), //
|
||||
date_optional_time("uuuu-MM-dd['T'HH:mm:ss.SSSXXX]"), //
|
||||
date_time("uuuu-MM-dd'T'HH:mm:ss.SSSXXX"), //
|
||||
date_time_no_millis("uuuu-MM-dd'T'HH:mm:ssVV"), // here Elasticsearch uses the zone-id in it's implementation
|
||||
date_time_no_millis("uuuu-MM-dd'T'HH:mm:ssVV"), // here Elasticsearch uses the zone-id in its implementation
|
||||
epoch_millis("epoch_millis"), //
|
||||
epoch_second("epoch_second"), //
|
||||
hour("HH"), //
|
||||
|
@ -53,9 +53,8 @@ public @interface Field {
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* The <em>name</em> to be used to store the field inside the document.
|
||||
* <p>
|
||||
* √5 If not set, the name of the annotated property is used.
|
||||
* The <em>name</em> to be used to store the field inside the document. If not set, the name of the annotated property
|
||||
* is used.
|
||||
*
|
||||
* @since 3.2
|
||||
*/
|
||||
|
@ -1031,6 +1031,7 @@ class RequestConverter {
|
||||
Assert.notNull(query, "query must not be null");
|
||||
Assert.notNull(indexCoordinates, "indexCoordinates must not be null");
|
||||
|
||||
elasticsearchConverter.updateQuery(query, clazz);
|
||||
SearchRequest.Builder builder = new SearchRequest.Builder();
|
||||
prepareSearchRequest(query, clazz, indexCoordinates, builder, forCount, useScroll);
|
||||
|
||||
|
@ -15,19 +15,29 @@
|
||||
*/
|
||||
package org.springframework.data.elasticsearch.core.query;
|
||||
|
||||
import org.springframework.data.elasticsearch.annotations.Field;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
/**
|
||||
* SourceFilter for providing includes and excludes.
|
||||
* SourceFilter for providing includes and excludes. Using these helps in reducing the amount of data that is returned
|
||||
* from Elasticsearch especially when the stored docuements are large and only some fields from these documents are
|
||||
* needed. If the SourceFilter includes the name of a property that has a different name mapped in Elasticsearch (see
|
||||
* {@link Field#name()} this will automatically be mapped.
|
||||
*
|
||||
* @author Jon Tsiros
|
||||
* @author Peter-Josef Meisch
|
||||
*/
|
||||
public interface SourceFilter {
|
||||
|
||||
/**
|
||||
* @return the name of the fields to include in a response.
|
||||
*/
|
||||
@Nullable
|
||||
String[] getIncludes();
|
||||
|
||||
/**
|
||||
* @return the names of the fields to exclude from a response.
|
||||
*/
|
||||
@Nullable
|
||||
String[] getExcludes();
|
||||
}
|
||||
|
@ -57,7 +57,6 @@ public abstract class AbstractElasticsearchRepositoryQuery implements Repository
|
||||
|
||||
protected void prepareQuery(Query query, Class<?> clazz, ParameterAccessor parameterAccessor) {
|
||||
|
||||
elasticsearchConverter.updateQuery(query, clazz);
|
||||
|
||||
if (queryMethod.hasAnnotatedHighlight()) {
|
||||
query.setHighlightQuery(queryMethod.getAnnotatedHighlightQuery());
|
||||
@ -68,5 +67,7 @@ public abstract class AbstractElasticsearchRepositoryQuery implements Repository
|
||||
if (sourceFilter != null) {
|
||||
query.addSourceFilter(sourceFilter);
|
||||
}
|
||||
|
||||
elasticsearchConverter.updateQuery(query, clazz);
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,9 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
}
|
||||
|
||||
private HighlightQuery createAnnotatedHighlightQuery() {
|
||||
|
||||
Assert.notNull(highlightAnnotation, "highlightAnnotation must not be null");
|
||||
|
||||
return new HighlightQuery(
|
||||
org.springframework.data.elasticsearch.core.query.highlight.Highlight.of(highlightAnnotation),
|
||||
getDomainClass());
|
||||
@ -140,6 +143,7 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
* @return the {@link ElasticsearchEntityMetadata} for the query methods {@link #getReturnedObjectType() return type}.
|
||||
* @since 3.2
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public ElasticsearchEntityMetadata<?> getEntityInformation() {
|
||||
|
||||
@ -260,23 +264,6 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
return queryAnnotation != null && queryAnnotation.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@literal true} if the method is annotated with {@link SourceFilters}.
|
||||
* @since 5.0
|
||||
*/
|
||||
public boolean hasSourceFilters() {
|
||||
return sourceFilters != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link SourceFilters} annotation for this method.
|
||||
* @since 5.0
|
||||
*/
|
||||
@Nullable
|
||||
public SourceFilters getSourceFilters() {
|
||||
return sourceFilters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses the sourceFilters property to create a {@link SourceFilter} to be added to a
|
||||
* {@link org.springframework.data.elasticsearch.core.query.Query}
|
||||
@ -295,29 +282,25 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
return null;
|
||||
}
|
||||
|
||||
ElasticsearchPersistentEntity<?> persistentEntity = converter.getMappingContext()
|
||||
.getPersistentEntity(getEntityInformation().getJavaType());
|
||||
|
||||
StringQueryUtil stringQueryUtil = new StringQueryUtil(converter.getConversionService());
|
||||
FetchSourceFilterBuilder fetchSourceFilterBuilder = new FetchSourceFilterBuilder();
|
||||
|
||||
if (sourceFilters.includes().length > 0) {
|
||||
fetchSourceFilterBuilder
|
||||
.withIncludes(mapParameters(sourceFilters.includes(), parameterAccessor, stringQueryUtil, persistentEntity));
|
||||
.withIncludes(mapParameters(sourceFilters.includes(), parameterAccessor, stringQueryUtil));
|
||||
}
|
||||
|
||||
if (sourceFilters.excludes().length > 0) {
|
||||
fetchSourceFilterBuilder
|
||||
.withExcludes(mapParameters(sourceFilters.excludes(), parameterAccessor, stringQueryUtil, persistentEntity));
|
||||
.withExcludes(mapParameters(sourceFilters.excludes(), parameterAccessor, stringQueryUtil));
|
||||
}
|
||||
|
||||
return fetchSourceFilterBuilder.build();
|
||||
}
|
||||
|
||||
private String[] mapParameters(String[] source, ParameterAccessor parameterAccessor, StringQueryUtil stringQueryUtil,
|
||||
@Nullable ElasticsearchPersistentEntity<?> persistentEntity) {
|
||||
private String[] mapParameters(String[] source, ParameterAccessor parameterAccessor, StringQueryUtil stringQueryUtil) {
|
||||
|
||||
List<String> unmappedFieldNames = new ArrayList<>();
|
||||
List<String> fieldNames = new ArrayList<>();
|
||||
|
||||
for (String s : source) {
|
||||
|
||||
@ -325,21 +308,17 @@ public class ElasticsearchQueryMethod extends QueryMethod {
|
||||
String fieldName = stringQueryUtil.replacePlaceholders(s, parameterAccessor);
|
||||
// this could be "[\"foo\",\"bar\"]", must be split
|
||||
if (fieldName.startsWith("[") && fieldName.endsWith("]")) {
|
||||
unmappedFieldNames.addAll( //
|
||||
//noinspection RegExpRedundantEscape
|
||||
fieldNames.addAll( //
|
||||
Arrays.asList(fieldName.substring(1, fieldName.length() - 2) //
|
||||
.replaceAll("\\\"", "") //
|
||||
.split(","))); //
|
||||
} else {
|
||||
unmappedFieldNames.add(fieldName);
|
||||
fieldNames.add(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return unmappedFieldNames.stream().map(fieldName -> {
|
||||
ElasticsearchPersistentProperty property = persistentEntity != null
|
||||
? persistentEntity.getPersistentProperty(fieldName)
|
||||
: null;
|
||||
return property != null ? property.getFieldName() : fieldName;
|
||||
}).toArray(String[]::new);
|
||||
return fieldNames.toArray(new String[0]);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user