Skip to content

Commit 56da910

Browse files
committed
Merge branch 'master' into cache-remote-shards-failed
2 parents a102531 + 02a4ef3 commit 56da910

File tree

353 files changed

+8881
-3184
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

353 files changed

+8881
-3184
lines changed

buildSrc/version.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
elasticsearch = 7.0.0-alpha1
2-
lucene = 7.4.0-snapshot-0a7c3f462f
2+
lucene = 7.4.0-snapshot-518d303506
33

44
# optional dependencies
55
spatial4j = 0.7

client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
5858
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
5959
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
60+
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
61+
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
6062
import org.elasticsearch.rest.RestStatus;
6163

6264
import java.io.IOException;
@@ -661,6 +663,36 @@ public void putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest, Re
661663
PutIndexTemplateResponse::fromXContent, listener, emptySet());
662664
}
663665

666+
/**
667+
* Validate a potentially expensive query without executing it.
668+
* <p>
669+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-validate.html"> Validate Query API
670+
* on elastic.co</a>
671+
* @param validateQueryRequest the request
672+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
673+
* @return the response
674+
* @throws IOException in case there is a problem sending the request or parsing back the response
675+
*/
676+
public ValidateQueryResponse validateQuery(ValidateQueryRequest validateQueryRequest, RequestOptions options) throws IOException {
677+
return restHighLevelClient.performRequestAndParseEntity(validateQueryRequest, RequestConverters::validateQuery, options,
678+
ValidateQueryResponse::fromXContent, emptySet());
679+
}
680+
681+
/**
682+
* Asynchronously validate a potentially expensive query without executing it.
683+
* <p>
684+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/search-validate.html"> Validate Query API
685+
* on elastic.co</a>
686+
* @param validateQueryRequest the request
687+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
688+
* @param listener the listener to be notified upon request completion
689+
*/
690+
public void validateQueryAsync(ValidateQueryRequest validateQueryRequest, RequestOptions options,
691+
ActionListener<ValidateQueryResponse> listener) {
692+
restHighLevelClient.performRequestAsyncAndParseEntity(validateQueryRequest, RequestConverters::validateQuery, options,
693+
ValidateQueryResponse::fromXContent, listener, emptySet());
694+
}
695+
664696
/**
665697
* Gets index templates using the Index Templates API
666698
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html"> Index Templates API

client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
5959
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
6060
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
61+
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
6162
import org.elasticsearch.action.bulk.BulkRequest;
6263
import org.elasticsearch.action.delete.DeleteRequest;
6364
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
@@ -856,6 +857,20 @@ static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) thro
856857
return request;
857858
}
858859

860+
static Request validateQuery(ValidateQueryRequest validateQueryRequest) throws IOException {
861+
String[] indices = validateQueryRequest.indices() == null ? Strings.EMPTY_ARRAY : validateQueryRequest.indices();
862+
String[] types = validateQueryRequest.types() == null || indices.length <= 0 ? Strings.EMPTY_ARRAY : validateQueryRequest.types();
863+
String endpoint = endpoint(indices, types, "_validate/query");
864+
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
865+
Params params = new Params(request);
866+
params.withIndicesOptions(validateQueryRequest.indicesOptions());
867+
params.putParam("explain", Boolean.toString(validateQueryRequest.explain()));
868+
params.putParam("all_shards", Boolean.toString(validateQueryRequest.allShards()));
869+
params.putParam("rewrite", Boolean.toString(validateQueryRequest.rewrite()));
870+
request.setEntity(createEntity(validateQueryRequest, REQUEST_BODY_CONTENT_TYPE));
871+
return request;
872+
}
873+
859874
static Request getAlias(GetAliasesRequest getAliasesRequest) {
860875
String[] indices = getAliasesRequest.indices() == null ? Strings.EMPTY_ARRAY : getAliasesRequest.indices();
861876
String[] aliases = getAliasesRequest.aliases() == null ? Strings.EMPTY_ARRAY : getAliasesRequest.aliases();

client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.elasticsearch.client;
2121

2222
import org.apache.http.client.methods.HttpGet;
23+
import org.apache.http.client.methods.HttpPost;
2324
import org.apache.http.client.methods.HttpPut;
2425
import org.elasticsearch.ElasticsearchException;
2526
import org.elasticsearch.ElasticsearchStatusException;
@@ -63,6 +64,8 @@
6364
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
6465
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
6566
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
67+
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
68+
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
6669
import org.elasticsearch.action.index.IndexRequest;
6770
import org.elasticsearch.action.support.IndicesOptions;
6871
import org.elasticsearch.action.support.WriteRequest;
@@ -80,6 +83,8 @@
8083
import org.elasticsearch.common.xcontent.json.JsonXContent;
8184
import org.elasticsearch.common.xcontent.support.XContentMapValues;
8285
import org.elasticsearch.index.IndexSettings;
86+
import org.elasticsearch.index.query.QueryBuilder;
87+
import org.elasticsearch.index.query.QueryBuilders;
8388
import org.elasticsearch.rest.RestStatus;
8489

8590
import java.io.IOException;
@@ -1155,6 +1160,40 @@ public void testPutTemplateBadRequests() throws Exception {
11551160
assertThat(unknownSettingError.getDetailedMessage(), containsString("unknown setting [index.this-setting-does-not-exist]"));
11561161
}
11571162

1163+
public void testValidateQuery() throws IOException{
1164+
String index = "some_index";
1165+
createIndex(index, Settings.EMPTY);
1166+
QueryBuilder builder = QueryBuilders
1167+
.boolQuery()
1168+
.must(QueryBuilders.queryStringQuery("*:*"))
1169+
.filter(QueryBuilders.termQuery("user", "kimchy"));
1170+
ValidateQueryRequest request = new ValidateQueryRequest(index).query(builder);
1171+
request.explain(randomBoolean());
1172+
ValidateQueryResponse response = execute(request, highLevelClient().indices()::validateQuery,
1173+
highLevelClient().indices()::validateQueryAsync);
1174+
assertTrue(response.isValid());
1175+
}
1176+
1177+
public void testInvalidValidateQuery() throws IOException{
1178+
String index = "shakespeare";
1179+
1180+
createIndex(index, Settings.EMPTY);
1181+
Request postDoc = new Request(HttpPost.METHOD_NAME, "/" + index + "/1");
1182+
postDoc.setJsonEntity(
1183+
"{\"type\":\"act\",\"line_id\":1,\"play_name\":\"Henry IV\", \"speech_number\":\"\"," +
1184+
"\"line_number\":\"\",\"speaker\":\"\",\"text_entry\":\"ACT I\"}");
1185+
assertOK(client().performRequest(postDoc));
1186+
1187+
QueryBuilder builder = QueryBuilders
1188+
.queryStringQuery("line_id:foo")
1189+
.lenient(false);
1190+
ValidateQueryRequest request = new ValidateQueryRequest(index).query(builder);
1191+
request.explain(true);
1192+
ValidateQueryResponse response = execute(request, highLevelClient().indices()::validateQuery,
1193+
highLevelClient().indices()::validateQueryAsync);
1194+
assertFalse(response.isValid());
1195+
}
1196+
11581197
public void testGetIndexTemplate() throws Exception {
11591198
RestHighLevelClient client = highLevelClient();
11601199

client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
6161
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
6262
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
63+
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
6364
import org.elasticsearch.action.bulk.BulkRequest;
6465
import org.elasticsearch.action.bulk.BulkShardRequest;
6566
import org.elasticsearch.action.delete.DeleteRequest;
@@ -1895,6 +1896,40 @@ public void testPutTemplateRequest() throws Exception {
18951896
assertToXContentBody(putTemplateRequest, request.getEntity());
18961897
}
18971898

1899+
public void testValidateQuery() throws Exception {
1900+
String[] indices = randomBoolean() ? null : randomIndicesNames(0, 5);
1901+
String[] types = randomBoolean() ? generateRandomStringArray(5, 5, false, false) : null;
1902+
ValidateQueryRequest validateQueryRequest;
1903+
if (randomBoolean()) {
1904+
validateQueryRequest = new ValidateQueryRequest(indices);
1905+
} else {
1906+
validateQueryRequest = new ValidateQueryRequest();
1907+
validateQueryRequest.indices(indices);
1908+
}
1909+
validateQueryRequest.types(types);
1910+
Map<String, String> expectedParams = new HashMap<>();
1911+
setRandomIndicesOptions(validateQueryRequest::indicesOptions, validateQueryRequest::indicesOptions, expectedParams);
1912+
validateQueryRequest.explain(randomBoolean());
1913+
validateQueryRequest.rewrite(randomBoolean());
1914+
validateQueryRequest.allShards(randomBoolean());
1915+
expectedParams.put("explain", Boolean.toString(validateQueryRequest.explain()));
1916+
expectedParams.put("rewrite", Boolean.toString(validateQueryRequest.rewrite()));
1917+
expectedParams.put("all_shards", Boolean.toString(validateQueryRequest.allShards()));
1918+
Request request = RequestConverters.validateQuery(validateQueryRequest);
1919+
StringJoiner endpoint = new StringJoiner("/", "/", "");
1920+
if (indices != null && indices.length > 0) {
1921+
endpoint.add(String.join(",", indices));
1922+
if (types != null && types.length > 0) {
1923+
endpoint.add(String.join(",", types));
1924+
}
1925+
}
1926+
endpoint.add("_validate/query");
1927+
assertThat(request.getEndpoint(), equalTo(endpoint.toString()));
1928+
assertThat(request.getParameters(), equalTo(expectedParams));
1929+
assertToXContentBody(validateQueryRequest, request.getEntity());
1930+
assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME));
1931+
}
1932+
18981933
public void testGetTemplateRequest() throws Exception {
18991934
Map<String, String> encodes = new HashMap<>();
19001935
encodes.put("log", "log");

client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package org.elasticsearch.client;
2121

2222
import com.fasterxml.jackson.core.JsonParseException;
23+
2324
import org.apache.http.Header;
2425
import org.apache.http.HttpEntity;
2526
import org.apache.http.HttpHost;
@@ -607,7 +608,7 @@ public void testDefaultNamedXContents() {
607608

608609
public void testProvidedNamedXContents() {
609610
List<NamedXContentRegistry.Entry> namedXContents = RestHighLevelClient.getProvidedNamedXContents();
610-
assertEquals(7, namedXContents.size());
611+
assertEquals(8, namedXContents.size());
611612
Map<Class<?>, Integer> categories = new HashMap<>();
612613
List<String> names = new ArrayList<>();
613614
for (NamedXContentRegistry.Entry namedXContent : namedXContents) {
@@ -625,9 +626,10 @@ public void testProvidedNamedXContents() {
625626
assertTrue(names.contains(PrecisionAtK.NAME));
626627
assertTrue(names.contains(DiscountedCumulativeGain.NAME));
627628
assertTrue(names.contains(MeanReciprocalRank.NAME));
628-
assertEquals(Integer.valueOf(2), categories.get(MetricDetail.class));
629+
assertEquals(Integer.valueOf(3), categories.get(MetricDetail.class));
629630
assertTrue(names.contains(PrecisionAtK.NAME));
630631
assertTrue(names.contains(MeanReciprocalRank.NAME));
632+
assertTrue(names.contains(DiscountedCumulativeGain.NAME));
631633
}
632634

633635
private static class TrackingActionListener implements ActionListener<Integer> {

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@
6262
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
6363
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
6464
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
65+
import org.elasticsearch.action.admin.indices.validate.query.QueryExplanation;
66+
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryRequest;
67+
import org.elasticsearch.action.admin.indices.validate.query.ValidateQueryResponse;
6568
import org.elasticsearch.action.support.ActiveShardCount;
6669
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
6770
import org.elasticsearch.action.support.IndicesOptions;
@@ -81,6 +84,7 @@
8184
import org.elasticsearch.common.xcontent.XContentBuilder;
8285
import org.elasticsearch.common.xcontent.XContentFactory;
8386
import org.elasticsearch.common.xcontent.XContentType;
87+
import org.elasticsearch.index.query.QueryBuilder;
8488
import org.elasticsearch.index.query.QueryBuilders;
8589
import org.elasticsearch.rest.RestStatus;
8690

@@ -2128,4 +2132,83 @@ public void onFailure(Exception e) {
21282132

21292133
assertTrue(latch.await(30L, TimeUnit.SECONDS));
21302134
}
2135+
2136+
public void testValidateQuery() throws IOException, InterruptedException {
2137+
RestHighLevelClient client = highLevelClient();
2138+
2139+
String index = "some_index";
2140+
createIndex(index, Settings.EMPTY);
2141+
2142+
// tag::validate-query-request
2143+
ValidateQueryRequest request = new ValidateQueryRequest(index); // <1>
2144+
// end::validate-query-request
2145+
2146+
// tag::validate-query-request-query
2147+
QueryBuilder builder = QueryBuilders
2148+
.boolQuery() // <1>
2149+
.must(QueryBuilders.queryStringQuery("*:*"))
2150+
.filter(QueryBuilders.termQuery("user", "kimchy"));
2151+
request.query(builder); // <2>
2152+
// end::validate-query-request-query
2153+
2154+
// tag::validate-query-request-explain
2155+
request.explain(true); // <1>
2156+
// end::validate-query-request-explain
2157+
2158+
// tag::validate-query-request-allShards
2159+
request.allShards(true); // <1>
2160+
// end::validate-query-request-allShards
2161+
2162+
// tag::validate-query-request-rewrite
2163+
request.rewrite(true); // <1>
2164+
// end::validate-query-request-rewrite
2165+
2166+
// tag::validate-query-execute
2167+
ValidateQueryResponse response = client.indices().validateQuery(request, RequestOptions.DEFAULT); // <1>
2168+
// end::validate-query-execute
2169+
2170+
// tag::validate-query-response
2171+
boolean isValid = response.isValid(); // <1>
2172+
int totalShards = response.getTotalShards(); // <2>
2173+
int successfulShards = response.getSuccessfulShards(); // <3>
2174+
int failedShards = response.getFailedShards(); // <4>
2175+
if (failedShards > 0) {
2176+
for(DefaultShardOperationFailedException failure: response.getShardFailures()) { // <5>
2177+
String failedIndex = failure.index(); // <6>
2178+
int shardId = failure.shardId(); // <7>
2179+
String reason = failure.reason(); // <8>
2180+
}
2181+
}
2182+
for(QueryExplanation explanation: response.getQueryExplanation()) { // <9>
2183+
String explanationIndex = explanation.getIndex(); // <10>
2184+
int shardId = explanation.getShard(); // <11>
2185+
String explanationString = explanation.getExplanation(); // <12>
2186+
}
2187+
// end::validate-query-response
2188+
2189+
// tag::validate-query-execute-listener
2190+
ActionListener<ValidateQueryResponse> listener =
2191+
new ActionListener<ValidateQueryResponse>() {
2192+
@Override
2193+
public void onResponse(ValidateQueryResponse validateQueryResponse) {
2194+
// <1>
2195+
}
2196+
2197+
@Override
2198+
public void onFailure(Exception e) {
2199+
// <2>
2200+
}
2201+
};
2202+
// end::validate-query-execute-listener
2203+
2204+
// Replace the empty listener by a blocking listener in test
2205+
final CountDownLatch latch = new CountDownLatch(1);
2206+
listener = new LatchedActionListener<>(listener, latch);
2207+
2208+
// tag::validate-query-execute-async
2209+
client.indices().validateQueryAsync(request, RequestOptions.DEFAULT, listener); // <1>
2210+
// end::validate-query-execute-async
2211+
2212+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
2213+
}
21312214
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client;
21+
22+
import java.util.Iterator;
23+
import java.util.List;
24+
import java.util.Map;
25+
26+
/**
27+
* A {@link NodeSelector} that selects nodes that have a particular value
28+
* for an attribute.
29+
*/
30+
public final class HasAttributeNodeSelector implements NodeSelector {
31+
private final String key;
32+
private final String value;
33+
34+
public HasAttributeNodeSelector(String key, String value) {
35+
this.key = key;
36+
this.value = value;
37+
}
38+
39+
@Override
40+
public void select(Iterable<Node> nodes) {
41+
Iterator<Node> itr = nodes.iterator();
42+
while (itr.hasNext()) {
43+
Map<String, List<String>> allAttributes = itr.next().getAttributes();
44+
if (allAttributes == null) continue;
45+
List<String> values = allAttributes.get(key);
46+
if (values == null || false == values.contains(value)) {
47+
itr.remove();
48+
}
49+
}
50+
}
51+
52+
@Override
53+
public String toString() {
54+
return key + "=" + value;
55+
}
56+
}

0 commit comments

Comments
 (0)