Add support for GetFieldMapping request in ReactiveElasticsearchClient.

Original Pull Request #1641
Closes #1640
This commit is contained in:
Farid Faoudi 2021-01-13 08:24:49 +01:00 committed by GitHub
parent 5bf0c4b093
commit 3c6dd641d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 142 additions and 0 deletions

View File

@ -22,6 +22,8 @@ import io.netty.handler.ssl.IdentityCipherSuiteFilter;
import io.netty.handler.ssl.JdkSslContext;
import io.netty.handler.timeout.ReadTimeoutHandler;
import io.netty.handler.timeout.WriteTimeoutHandler;
import org.elasticsearch.client.indices.GetFieldMappingsRequest;
import org.elasticsearch.client.indices.GetFieldMappingsResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.netty.http.client.HttpClient;
@ -139,6 +141,7 @@ import org.springframework.web.reactive.function.client.WebClient.RequestBodySpe
* @author Russell Parry
* @author Thomas Geese
* @author Brian Clozel
* @author Farid Faoudi
* @since 3.2
* @see ClientConfiguration
* @see ReactiveRestClients
@ -674,6 +677,11 @@ public class DefaultReactiveElasticsearchClient implements ReactiveElasticsearch
return sendRequest(getMappingsRequest, requestCreator.getMapping(), GetMappingsResponse.class, headers).next();
}
@Override
public Mono<GetFieldMappingsResponse> getFieldMapping(HttpHeaders headers, GetFieldMappingsRequest getFieldMappingsRequest) {
return sendRequest(getFieldMappingsRequest, requestCreator.getFieldMapping(), GetFieldMappingsResponse.class, headers).next();
}
@Override
public Mono<GetSettingsResponse> getSettings(HttpHeaders headers, GetSettingsRequest getSettingsRequest) {
return sendRequest(getSettingsRequest, requestCreator.getSettings(), GetSettingsResponse.class, headers).next();

View File

@ -15,6 +15,8 @@
*/
package org.springframework.data.elasticsearch.client.reactive;
import org.elasticsearch.client.indices.GetFieldMappingsRequest;
import org.elasticsearch.client.indices.GetFieldMappingsResponse;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -77,6 +79,7 @@ import org.springframework.web.reactive.function.client.WebClient;
* @author Peter-Josef Meisch
* @author Henrique Amaral
* @author Thomas Geese
* @author Farid Faoudi
* @since 3.2
* @see ClientConfiguration
* @see ReactiveRestClients
@ -1162,6 +1165,50 @@ public interface ReactiveElasticsearchClient {
*/
Mono<GetMappingsResponse> getMapping(HttpHeaders headers, GetMappingsRequest getMappingsRequest);
/**
* Execute the given {@link GetFieldMappingsRequest} against the {@literal indices} API.
*
* @param consumer never {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html"> Indices
* Flush API on elastic.co</a>
* @since 4.2
*/
default Mono<GetFieldMappingsResponse> getFieldMapping(Consumer<GetFieldMappingsRequest> consumer) {
GetFieldMappingsRequest request = new GetFieldMappingsRequest();
consumer.accept(request);
return getFieldMapping(request);
}
/**
* Execute the given {@link GetFieldMappingsRequest} against the {@literal indices} API.
*
* @param getFieldMappingsRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html"> Indices
* Flush API on elastic.co</a>
* @since 4.2
*/
default Mono<GetFieldMappingsResponse> getFieldMapping(GetFieldMappingsRequest getFieldMappingsRequest) {
return getFieldMapping(HttpHeaders.EMPTY, getFieldMappingsRequest);
}
/**
* Execute the given {@link GetFieldMappingsRequest} against the {@literal indices} API.
*
* @param headers Use {@link HttpHeaders} to provide eg. authentication data. Must not be {@literal null}.
* @param getFieldMappingsRequest must not be {@literal null}.
* @return a {@link Mono} signalling operation completion or an {@link Mono#error(Throwable) error} if eg. the index
* does not exist.
* @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-get-field-mapping.html"> Indices
* Flush API on elastic.co</a>
* @since 4.2
*/
Mono<GetFieldMappingsResponse> getFieldMapping(HttpHeaders headers, GetFieldMappingsRequest getFieldMappingsRequest);
/**
* Execute the given {@link IndicesAliasesRequest} against the {@literal indices} API.
*

View File

@ -28,6 +28,7 @@ import org.elasticsearch.action.search.SearchScrollRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.indices.GetFieldMappingsRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
@ -37,6 +38,7 @@ import org.springframework.data.elasticsearch.client.util.RequestConverters;
/**
* @author Roman Puchkovskiy
* @author Farid Faoudi
* @since 4.0
*/
public interface RequestCreator {
@ -194,4 +196,11 @@ public interface RequestCreator {
default Function<DeleteIndexTemplateRequest, Request> deleteTemplate() {
return RequestConverters::deleteTemplate;
}
/**
* @since 4.2
*/
default Function<GetFieldMappingsRequest, Request> getFieldMapping() {
return RequestConverters::getFieldMapping;
}
}

View File

@ -71,6 +71,7 @@ import org.elasticsearch.client.Requests;
import org.elasticsearch.client.RethrottleRequest;
import org.elasticsearch.client.core.CountRequest;
import org.elasticsearch.client.indices.AnalyzeRequest;
import org.elasticsearch.client.indices.GetFieldMappingsRequest;
import org.elasticsearch.client.indices.GetIndexTemplatesRequest;
import org.elasticsearch.client.indices.IndexTemplatesExistRequest;
import org.elasticsearch.client.indices.PutIndexTemplateRequest;
@ -115,6 +116,7 @@ import org.springframework.lang.Nullable;
*
* @author Christoph Strobl
* @author Peter-Josef Meisch
* @author Farid Faoudi
* @since 3.2
*/
@SuppressWarnings("JavadocReference")
@ -891,6 +893,24 @@ public class RequestConverters {
return request;
}
public static Request getFieldMapping(GetFieldMappingsRequest getFieldMappingsRequest) {
String[] indices = getFieldMappingsRequest.indices() == null ? Strings.EMPTY_ARRAY : getFieldMappingsRequest.indices();
String[] fields = getFieldMappingsRequest.fields() == null ? Strings.EMPTY_ARRAY : getFieldMappingsRequest.fields();
final String endpoint = new EndpointBuilder().addCommaSeparatedPathParts(indices)
.addPathPartAsIs("_mapping").addPathPartAsIs("field")
.addCommaSeparatedPathParts(fields)
.build();
Request request = new Request(HttpMethod.GET.name(), endpoint);
RequestConverters.Params parameters = new Params(request);
parameters.withIndicesOptions(getFieldMappingsRequest.indicesOptions());
parameters.withIncludeDefaults(getFieldMappingsRequest.includeDefaults());
parameters.withIncludeTypeName(false);
return request;
}
static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) {
try {

View File

@ -18,12 +18,14 @@ package org.springframework.data.elasticsearch.client.reactive;
import static org.assertj.core.api.Assertions.*;
import lombok.SneakyThrows;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import reactor.core.publisher.Mono;
import reactor.test.StepVerifier;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
@ -73,6 +75,7 @@ import org.springframework.test.context.ContextConfiguration;
* @author Henrique Amaral
* @author Russell Parry
* @author Thomas Geese
* @author Farid Faoudi
*/
@SpringIntegrationTest
@ContextConfiguration(classes = { ReactiveElasticsearchClientIntegrationTests.Config.class })
@ -721,6 +724,61 @@ public class ReactiveElasticsearchClientIntegrationTests {
.verifyComplete();
}
@Test // #1640
void getFieldMapping() {
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
Map<String, Object> properties = new HashMap<>();
properties.put("message1", Collections.singletonMap("type", "text"));
properties.put("message2", Collections.singletonMap("type", "keyword"));
Map<String, Object> jsonMap = Collections.singletonMap("properties", properties);
final PutMappingRequest putMappingRequest = new PutMappingRequest(INDEX_I)
.source(jsonMap);
client.indices().putMapping(putMappingRequest).block();
client.indices().getFieldMapping(request -> request.indices(INDEX_I).fields("message1", "message2"))
.as(StepVerifier::create)
.consumeNextWith(it -> {
assertThat(it.mappings().get(INDEX_I).keySet().size()).isEqualTo(2);
assertThat(it.mappings().get(INDEX_I).get("message1").sourceAsMap()).isEqualTo(Collections.singletonMap("message1", Collections.singletonMap("type", "text")));
assertThat(it.mappings().get(INDEX_I).get("message2").sourceAsMap()).isEqualTo(Collections.singletonMap("message2", Collections.singletonMap("type", "keyword")));
})
.verifyComplete();
}
@Test // #1640
void getFieldMappingNonExistingField() {
operations.indexOps(IndexCoordinates.of(INDEX_I)).create().block();
Map<String, Object> jsonMap = Collections.singletonMap("properties",
Collections.singletonMap("message", Collections.singletonMap("type", "text")));
final PutMappingRequest putMappingRequest = new PutMappingRequest(INDEX_I)
.source(jsonMap);
client.indices().putMapping(putMappingRequest).block();
client.indices().getFieldMapping(request -> request.indices(INDEX_I).fields("message1"))
.as(StepVerifier::create)
.consumeNextWith(it -> {
assertThat(it.mappings().get(INDEX_I).keySet().size()).isZero();
})
.verifyComplete();
}
@Test // #1640
void getFieldMappingNonExistingIndex() {
client.indices().getFieldMapping(request -> request.indices(INDEX_I).fields("message1"))
.as(StepVerifier::create)
.verifyError(ElasticsearchStatusException.class);
}
@Test // DATAES-796
@DisplayName("should return the whole SearchResponse")
void shouldReturnTheWholeSearchResponse() {