Skip to content

Commit

Permalink
Merge branch 'master' into compile-with-jdk-9
Browse files Browse the repository at this point in the history
* master:
  Revert "[Docs] Fix Java Api index administration usage (elastic#28133)"
  Revert "[Docs] Fix base directory to include for put_mapping.asciidoc"
  Added multi get api to the high level rest client.
  [Docs] Clarify numeric datatype ranges (elastic#28240)
  • Loading branch information
jasontedor committed Jan 16, 2018
2 parents 6860f66 + 8a58df4 commit faef9bd
Show file tree
Hide file tree
Showing 13 changed files with 518 additions and 127 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.action.search.MultiSearchRequest;
Expand Down Expand Up @@ -312,6 +313,15 @@ static Request get(GetRequest getRequest) {
return new Request(HttpGet.METHOD_NAME, endpoint, parameters.getParams(), null);
}

static Request multiGet(MultiGetRequest multiGetRequest) throws IOException {
Params parameters = Params.builder();
parameters.withPreference(multiGetRequest.preference());
parameters.withRealtime(multiGetRequest.realtime());
parameters.withRefresh(multiGetRequest.refresh());
HttpEntity entity = createEntity(multiGetRequest, REQUEST_BODY_CONTENT_TYPE);
return new Request(HttpGet.METHOD_NAME, "/_mget", parameters.getParams(), entity);
}

static Request index(IndexRequest indexRequest) {
String method = Strings.hasLength(indexRequest.id()) ? HttpPut.METHOD_NAME : HttpPost.METHOD_NAME;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.main.MainRequest;
Expand Down Expand Up @@ -289,6 +291,25 @@ public final void getAsync(GetRequest getRequest, ActionListener<GetResponse> li
performRequestAsyncAndParseEntity(getRequest, Request::get, GetResponse::fromXContent, listener, singleton(404), headers);
}

/**
* Retrieves multiple documents by id using the Multi Get API
*
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html">Multi Get API on elastic.co</a>
*/
public final MultiGetResponse multiGet(MultiGetRequest multiGetRequest, Header... headers) throws IOException {
return performRequestAndParseEntity(multiGetRequest, Request::multiGet, MultiGetResponse::fromXContent, singleton(404), headers);
}

/**
* Asynchronously retrieves multiple documents by id using the Multi Get API
*
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-multi-get.html">Multi Get API on elastic.co</a>
*/
public void multiGetAsync(MultiGetRequest multiGetRequest, ActionListener<MultiGetResponse> listener, Header... headers) {
performRequestAsyncAndParseEntity(multiGetRequest, Request::multiGet, MultiGetResponse::fromXContent, listener,
singleton(404), headers);
}

/**
* Checks for the existence of a document. Returns true if it exists, false otherwise
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.get.MultiGetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
Expand Down Expand Up @@ -238,6 +240,64 @@ public void testGet() throws IOException {
}
}

public void testMultiGet() throws IOException {
{
MultiGetRequest multiGetRequest = new MultiGetRequest();
multiGetRequest.add("index", "type", "id1");
multiGetRequest.add("index", "type", "id2");
MultiGetResponse response = execute(multiGetRequest, highLevelClient()::multiGet, highLevelClient()::multiGetAsync);
assertEquals(2, response.getResponses().length);

assertTrue(response.getResponses()[0].isFailed());
assertNull(response.getResponses()[0].getResponse());
assertEquals("id1", response.getResponses()[0].getFailure().getId());
assertEquals("type", response.getResponses()[0].getFailure().getType());
assertEquals("index", response.getResponses()[0].getFailure().getIndex());
assertEquals("Elasticsearch exception [type=index_not_found_exception, reason=no such index]",
response.getResponses()[0].getFailure().getFailure().getMessage());

assertTrue(response.getResponses()[1].isFailed());
assertNull(response.getResponses()[1].getResponse());
assertEquals("id2", response.getResponses()[1].getId());
assertEquals("type", response.getResponses()[1].getType());
assertEquals("index", response.getResponses()[1].getIndex());
assertEquals("Elasticsearch exception [type=index_not_found_exception, reason=no such index]",
response.getResponses()[1].getFailure().getFailure().getMessage());
}

String document = "{\"field\":\"value1\"}";
StringEntity stringEntity = new StringEntity(document, ContentType.APPLICATION_JSON);
Response r = client().performRequest("PUT", "/index/type/id1", Collections.singletonMap("refresh", "true"), stringEntity);
assertEquals(201, r.getStatusLine().getStatusCode());

document = "{\"field\":\"value2\"}";
stringEntity = new StringEntity(document, ContentType.APPLICATION_JSON);
r = client().performRequest("PUT", "/index/type/id2", Collections.singletonMap("refresh", "true"), stringEntity);
assertEquals(201, r.getStatusLine().getStatusCode());

{
MultiGetRequest multiGetRequest = new MultiGetRequest();
multiGetRequest.add("index", "type", "id1");
multiGetRequest.add("index", "type", "id2");
MultiGetResponse response = execute(multiGetRequest, highLevelClient()::multiGet, highLevelClient()::multiGetAsync);
assertEquals(2, response.getResponses().length);

assertFalse(response.getResponses()[0].isFailed());
assertNull(response.getResponses()[0].getFailure());
assertEquals("id1", response.getResponses()[0].getId());
assertEquals("type", response.getResponses()[0].getType());
assertEquals("index", response.getResponses()[0].getIndex());
assertEquals(Collections.singletonMap("field", "value1"), response.getResponses()[0].getResponse().getSource());

assertFalse(response.getResponses()[1].isFailed());
assertNull(response.getResponses()[1].getFailure());
assertEquals("id2", response.getResponses()[1].getId());
assertEquals("type", response.getResponses()[1].getType());
assertEquals("index", response.getResponses()[1].getIndex());
assertEquals(Collections.singletonMap("field", "value2"), response.getResponses()[1].getResponse().getSource());
}
}

public void testIndex() throws IOException {
final XContentType xContentType = randomFrom(XContentType.values());
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.elasticsearch.action.bulk.BulkShardRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.MultiGetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.ClearScrollRequest;
import org.elasticsearch.action.search.MultiSearchRequest;
Expand Down Expand Up @@ -147,6 +148,59 @@ public void testGet() {
getAndExistsTest(Request::get, "GET");
}

public void testMultiGet() throws IOException {
Map<String, String> expectedParams = new HashMap<>();
MultiGetRequest multiGetRequest = new MultiGetRequest();
if (randomBoolean()) {
String preference = randomAlphaOfLength(4);
multiGetRequest.preference(preference);
expectedParams.put("preference", preference);
}
if (randomBoolean()) {
multiGetRequest.realtime(randomBoolean());
if (multiGetRequest.realtime() == false) {
expectedParams.put("realtime", "false");
}
}
if (randomBoolean()) {
multiGetRequest.refresh(randomBoolean());
if (multiGetRequest.refresh()) {
expectedParams.put("refresh", "true");
}
}

int numberOfRequests = randomIntBetween(0, 32);
for (int i = 0; i < numberOfRequests; i++) {
MultiGetRequest.Item item =
new MultiGetRequest.Item(randomAlphaOfLength(4), randomAlphaOfLength(4), randomAlphaOfLength(4));
if (randomBoolean()) {
item.routing(randomAlphaOfLength(4));
}
if (randomBoolean()) {
item.parent(randomAlphaOfLength(4));
}
if (randomBoolean()) {
item.storedFields(generateRandomStringArray(16, 8, false));
}
if (randomBoolean()) {
item.version(randomNonNegativeLong());
}
if (randomBoolean()) {
item.versionType(randomFrom(VersionType.values()));
}
if (randomBoolean()) {
randomizeFetchSourceContextParams(item::fetchSourceContext, new HashMap<>());
}
multiGetRequest.add(item);
}

Request request = Request.multiGet(multiGetRequest);
assertEquals("GET", request.getMethod());
assertEquals("/_mget", request.getEndpoint());
assertEquals(expectedParams, request.getParameters());
assertToXContentBody(multiGetRequest, request.getEntity());
}

public void testDelete() {
String index = randomAlphaOfLengthBetween(3, 10);
String type = randomAlphaOfLengthBetween(3, 10);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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.elasticsearch.action.get;

import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.get.GetResult;
import org.elasticsearch.test.ESTestCase;

import java.io.IOException;

import static org.elasticsearch.test.XContentTestUtils.insertRandomFields;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

public class MultiGetResponseTests extends ESTestCase {

public void testFromXContent() throws IOException {
for (int runs = 0; runs < 20; runs++) {
MultiGetResponse expected = createTestInstance();
XContentType xContentType = randomFrom(XContentType.values());
BytesReference shuffled = toShuffledXContent(expected, xContentType, ToXContent.EMPTY_PARAMS, false);

XContentParser parser = createParser(XContentFactory.xContent(xContentType), shuffled);
MultiGetResponse parsed = MultiGetResponse.fromXContent(parser);
assertNull(parser.nextToken());
assertNotSame(expected, parsed);

assertThat(parsed.getResponses().length, equalTo(expected.getResponses().length));
for (int i = 0; i < expected.getResponses().length; i++) {
MultiGetItemResponse expectedItem = expected.getResponses()[i];
MultiGetItemResponse actualItem = parsed.getResponses()[i];
assertThat(actualItem.getIndex(), equalTo(expectedItem.getIndex()));
assertThat(actualItem.getType(), equalTo(expectedItem.getType()));
assertThat(actualItem.getId(), equalTo(expectedItem.getId()));
if (expectedItem.isFailed()) {
assertThat(actualItem.isFailed(), is(true));
assertThat(actualItem.getFailure().getMessage(), containsString(expectedItem.getFailure().getMessage()));
} else {
assertThat(actualItem.isFailed(), is(false));
assertThat(actualItem.getResponse(), equalTo(expectedItem.getResponse()));
}
}
}
}

private static MultiGetResponse createTestInstance() {
MultiGetItemResponse[] items = new MultiGetItemResponse[randomIntBetween(0, 128)];
for (int i = 0; i < items.length; i++) {
if (randomBoolean()) {
items[i] = new MultiGetItemResponse(new GetResponse(new GetResult(
randomAlphaOfLength(4), randomAlphaOfLength(4), randomAlphaOfLength(4), randomNonNegativeLong(),
true, null, null
)), null);
} else {
items[i] = new MultiGetItemResponse(null, new MultiGetResponse.Failure(randomAlphaOfLength(4),
randomAlphaOfLength(4), randomAlphaOfLength(4), new RuntimeException(randomAlphaOfLength(4))));
}
}
return new MultiGetResponse(items);
}

}
57 changes: 48 additions & 9 deletions docs/java-api/admin/indices/put-mapping.asciidoc
Original file line number Diff line number Diff line change
@@ -1,23 +1,54 @@
[[java-admin-indices-put-mapping]]
:base-dir: {docdir}/../../server/src/test/java/org/elasticsearch/action/admin/indices/create

==== Put Mapping

The PUT mapping API allows you to add a new type while creating an index:

["source","java",subs="attributes,callouts,macros"]
[source,java]
--------------------------------------------------
include-tagged::{base-dir}/CreateIndexIT.java[addMapping-create-index-request]
client.admin().indices().prepareCreate("twitter") <1>
.addMapping("tweet", "{\n" + <2>
" \"tweet\": {\n" +
" \"properties\": {\n" +
" \"message\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
" }\n" +
" }")
.get();
--------------------------------------------------
<1> <<java-admin-indices-create-index,Creates an index>> called `twitter`
<2> It also adds a `tweet` mapping type.


The PUT mapping API also allows to add a new type to an existing index:

["source","java",subs="attributes,callouts,macros"]
[source,java]
--------------------------------------------------
include-tagged::{base-dir}/CreateIndexIT.java[putMapping-request-source]
client.admin().indices().preparePutMapping("twitter") <1>
.setType("user") <2>
.setSource("{\n" + <3>
" \"properties\": {\n" +
" \"name\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
"}")
.get();
// You can also provide the type in the source document
client.admin().indices().preparePutMapping("twitter")
.setType("user")
.setSource("{\n" +
" \"user\":{\n" + <4>
" \"properties\": {\n" +
" \"name\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}")
.get();
--------------------------------------------------
<1> Puts a mapping on existing index called `twitter`
<2> Adds a `user` mapping type.
Expand All @@ -26,12 +57,20 @@ include-tagged::{base-dir}/CreateIndexIT.java[putMapping-request-source]

You can use the same API to update an existing mapping:

["source","java",subs="attributes,callouts,macros"]
[source,java]
--------------------------------------------------
include-tagged::{base-dir}/CreateIndexIT.java[putMapping-request-source-append]
client.admin().indices().preparePutMapping("twitter") <1>
.setType("user") <2>
.setSource("{\n" + <3>
" \"properties\": {\n" +
" \"user_name\": {\n" +
" \"type\": \"text\"\n" +
" }\n" +
" }\n" +
"}")
.get();
--------------------------------------------------
<1> Puts a mapping on existing index called `twitter`
<2> Updates the `user` mapping type.
<3> This `user` has now a new field `user_name`

:base-dir!:
6 changes: 3 additions & 3 deletions docs/reference/mapping/types/numeric.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ The following numeric types are supported:
`integer`:: A signed 32-bit integer with a minimum value of +-2^31^+ and a maximum value of +2^31^-1+.
`short`:: A signed 16-bit integer with a minimum value of +-32,768+ and a maximum value of +32,767+.
`byte`:: A signed 8-bit integer with a minimum value of +-128+ and a maximum value of +127+.
`double`:: A double-precision 64-bit IEEE 754 floating point number.
`float`:: A single-precision 32-bit IEEE 754 floating point number.
`half_float`:: A half-precision 16-bit IEEE 754 floating point number.
`double`:: A double-precision 64-bit IEEE 754 floating point number, restricted to finite values.
`float`:: A single-precision 32-bit IEEE 754 floating point number, restricted to finite values.
`half_float`:: A half-precision 16-bit IEEE 754 floating point number, restricted to finite values.
`scaled_float`:: A floating point number that is backed by a `long`, scaled by a fixed `double` scaling factor.

Below is an example of configuring a mapping with numeric fields:
Expand Down
Loading

0 comments on commit faef9bd

Please sign in to comment.