simplify builder API with simpler get()

also simplify some common API calls, for example, a simplified format in Java API for providing mapping
This commit is contained in:
Shay Banon 2013-07-02 12:10:24 +02:00
parent 98bd5a0e66
commit 8919e7e602
14 changed files with 207 additions and 31 deletions

View File

@ -19,8 +19,10 @@
package org.elasticsearch.action;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.support.PlainListenableActionFuture;
import org.elasticsearch.client.internal.InternalGenericClient;
import org.elasticsearch.common.unit.TimeValue;
/**
*
@ -58,6 +60,27 @@ public abstract class ActionRequestBuilder<Request extends ActionRequest, Respon
return future;
}
/**
* Short version of execute().actionGet().
*/
public Response get() throws ElasticSearchException {
return execute().actionGet();
}
/**
* Short version of execute().actionGet().
*/
public Response get(TimeValue timeout) throws ElasticSearchException {
return execute().actionGet(timeout);
}
/**
* Short version of execute().actionGet().
*/
public Response get(String timeout) throws ElasticSearchException {
return execute().actionGet(timeout);
}
public void execute(ActionListener<Response> listener) {
doExecute(listener);
}

View File

@ -24,6 +24,7 @@ import org.elasticsearch.ElasticSearchGenerationException;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.ElasticSearchParseException;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.bytes.BytesArray;
@ -125,6 +126,14 @@ public class CreateIndexRequest extends MasterNodeOperationRequest<CreateIndexRe
return cause;
}
/**
* A simplified version of settings that takes key value pairs settings.
*/
public CreateIndexRequest settings(Object... settings) {
this.settings = ImmutableSettings.builder().put(settings).build();
return this;
}
/**
* The settings to created the index with.
*/
@ -229,6 +238,15 @@ public class CreateIndexRequest extends MasterNodeOperationRequest<CreateIndexRe
}
}
/**
* A specialized simplified mapping source method, takes the form of simple properties definition:
* ("field1", "type=string,store=true").
*/
public CreateIndexRequest mapping(String type, Object... source) {
mapping(type, PutMappingRequest.buildFromSimplifiedDef(type, source));
return this;
}
/**
* Sets the settings and mappings as a single source.
*/

View File

@ -81,6 +81,14 @@ public class CreateIndexRequestBuilder extends MasterNodeOperationRequestBuilder
return this;
}
/**
* A simplified version of settings that takes key value pairs settings.
*/
public CreateIndexRequestBuilder setSettings(Object... settings) {
request.settings(settings);
return this;
}
/**
* The settings to crete the index with (either json/yaml/properties format)
*/
@ -130,6 +138,15 @@ public class CreateIndexRequestBuilder extends MasterNodeOperationRequestBuilder
return this;
}
/**
* A specialized simplified mapping source method, takes the form of simple properties definition:
* ("field1", "type=string,store=true").
*/
public CreateIndexRequestBuilder addMapping(String type, Object... source) {
request.mapping(type, source);
return this;
}
/**
* Sets the settings and mappings as a single source.
*/

View File

@ -24,6 +24,7 @@ import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.common.Required;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.unit.TimeValue;
@ -123,6 +124,45 @@ public class PutMappingRequest extends MasterNodeOperationRequest<PutMappingRequ
return source;
}
/**
* A specialized simplified mapping source method, takes the form of simple properties definition:
* ("field1", "type=string,store=true").
*/
public PutMappingRequest source(Object... source) {
return source(buildFromSimplifiedDef(type, source));
}
public static XContentBuilder buildFromSimplifiedDef(String type, Object... source) {
try {
XContentBuilder builder = XContentFactory.jsonBuilder();
builder.startObject();
if (type != null) {
builder.startObject(type);
}
builder.startObject("properties");
for (int i = 0; i < source.length; i++) {
builder.startObject(source[i++].toString());
String[] s1 = Strings.splitStringByCommaToArray(source[i].toString());
for (String s : s1) {
String[] s2 = Strings.split(s, "=");
if (s2.length != 2) {
throw new ElasticSearchIllegalArgumentException("malformed " + s);
}
builder.field(s2[0], s2[1]);
}
builder.endObject();
}
builder.endObject();
if (type != null) {
builder.endObject();
}
builder.endObject();
return builder;
} catch (Exception e) {
throw new ElasticSearchIllegalArgumentException("failed to generate simplified mapping definition", e);
}
}
/**
* The mapping source definition.
*/

View File

@ -76,6 +76,15 @@ public class PutMappingRequestBuilder extends MasterNodeOperationRequestBuilder<
return this;
}
/**
* A specialized simplified mapping source method, takes the form of simple properties definition:
* ("field1", "type=string,store=true").
*/
public PutMappingRequestBuilder setSource(Object... source) {
request.source(source);
return this;
}
/**
* Timeout to wait till the put mapping gets acknowledged of all current cluster nodes. Defaults to
* <tt>10s</tt>.

View File

@ -411,6 +411,21 @@ public class IndexRequest extends ShardReplicationOperationRequest<IndexRequest>
}
}
@Required
public IndexRequest source(Object... source) {
try {
XContentBuilder builder = XContentFactory.contentBuilder(contentType);
builder.startObject();
for (int i = 0; i < source.length; i++) {
builder.field(source[i++].toString(), source[i]);
}
builder.endObject();
return source(builder);
} catch (IOException e) {
throw new ElasticSearchGenerationException("Failed to generate", e);
}
}
/**
* Sets the document to index in bytes form.
*/

View File

@ -202,6 +202,14 @@ public class IndexRequestBuilder extends ShardReplicationOperationRequestBuilder
return this;
}
/**
* Constructs a simple document with a field name and value pairs.
*/
public IndexRequestBuilder setSource(Object... source) {
request.source(source);
return this;
}
/**
* The content type that will be used to generate a document from user provided objects (like Map).
*/

View File

@ -430,6 +430,15 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
return this;
}
/**
* Sets the doc to use for updates when a script is not specified, the doc provided
* is a field and value pairs.
*/
public UpdateRequest doc(Object... source) {
safeDoc().source(source);
return this;
}
/**
* Sets the doc to use for updates when a script is not specified.
*/
@ -506,6 +515,15 @@ public class UpdateRequest extends InstanceShardOperationRequest<UpdateRequest>
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists. The doc
* includes field and value pairs.
*/
public UpdateRequest upsert(Object... source) {
safeUpsertRequest().source(source);
return this;
}
public IndexRequest upsertRequest() {
return this.upsertRequest;
}

View File

@ -243,11 +243,20 @@ public class UpdateRequestBuilder extends InstanceShardOperationRequestBuilder<U
return this;
}
/**
* Sets the doc to use for updates when a script is not specified, the doc provided
* is a field and value pairs.
*/
public UpdateRequestBuilder setDoc(Object... source) {
request.doc(source);
return this;
}
/**
* Sets the index request to be used if the document does not exists. Otherwise, a {@link org.elasticsearch.index.engine.DocumentMissingException}
* is thrown.
*/
public UpdateRequestBuilder setUpsertRequest(IndexRequest indexRequest) {
public UpdateRequestBuilder setUpsert(IndexRequest indexRequest) {
request.upsert(indexRequest);
return this;
}
@ -255,7 +264,7 @@ public class UpdateRequestBuilder extends InstanceShardOperationRequestBuilder<U
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequestBuilder setUpsertRequest(XContentBuilder source) {
public UpdateRequestBuilder setUpsert(XContentBuilder source) {
request.upsert(source);
return this;
}
@ -263,7 +272,7 @@ public class UpdateRequestBuilder extends InstanceShardOperationRequestBuilder<U
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequestBuilder setUpsertRequest(Map source) {
public UpdateRequestBuilder setUpsert(Map source) {
request.upsert(source);
return this;
}
@ -271,7 +280,7 @@ public class UpdateRequestBuilder extends InstanceShardOperationRequestBuilder<U
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequestBuilder setUpsertRequest(Map source, XContentType contentType) {
public UpdateRequestBuilder setUpsert(Map source, XContentType contentType) {
request.upsert(source, contentType);
return this;
}
@ -279,7 +288,7 @@ public class UpdateRequestBuilder extends InstanceShardOperationRequestBuilder<U
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequestBuilder setUpsertRequest(String source) {
public UpdateRequestBuilder setUpsert(String source) {
request.upsert(source);
return this;
}
@ -287,7 +296,7 @@ public class UpdateRequestBuilder extends InstanceShardOperationRequestBuilder<U
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequestBuilder setUpsertRequest(byte[] source) {
public UpdateRequestBuilder setUpsert(byte[] source) {
request.upsert(source);
return this;
}
@ -295,11 +304,20 @@ public class UpdateRequestBuilder extends InstanceShardOperationRequestBuilder<U
/**
* Sets the doc source of the update request to be used when the document does not exists.
*/
public UpdateRequestBuilder setUpsertRequest(byte[] source, int offset, int length) {
public UpdateRequestBuilder setUpsert(byte[] source, int offset, int length) {
request.upsert(source, offset, length);
return this;
}
/**
* Sets the doc source of the update request to be used when the document does not exists. The doc
* includes field and value pairs.
*/
public UpdateRequestBuilder setUpsert(Object... source) {
request.upsert(source);
return this;
}
public UpdateRequestBuilder setSource(XContentBuilder source) throws Exception {
request.source(source);
return this;

View File

@ -524,6 +524,17 @@ public class ImmutableSettings implements Settings {
return map.get(toCamelCase(key));
}
/**
* Puts tuples of key value pairs of settings. Simplified version instead of repeating calling
* put for each one.
*/
public Builder put(Object... settings) {
for (int i = 0; i < settings.length; i++) {
put(settings[i++].toString(), settings[i].toString());
}
return this;
}
/**
* Sets a setting with the provided setting key and value.
*

View File

@ -78,7 +78,7 @@ public class BulkTests extends AbstractSharedClusterTest {
bulkResponse = client().prepareBulk()
.add(client().prepareUpdate().setIndex("test").setType("type1").setId("6").setScript("ctx._source.field += 1")
.setUpsertRequest(jsonBuilder().startObject().field("field", 0).endObject()))
.setUpsert(jsonBuilder().startObject().field("field", 0).endObject()))
.add(client().prepareUpdate().setIndex("test").setType("type1").setId("7").setScript("ctx._source.field += 1"))
.add(client().prepareUpdate().setIndex("test").setType("type1").setId("2").setScript("ctx._source.field += 1"))
.execute().actionGet();
@ -216,7 +216,7 @@ public class BulkTests extends AbstractSharedClusterTest {
client().prepareUpdate()
.setIndex("test").setType("type1").setId(Integer.toString(i))
.setScript("ctx._source.counter += 1").setFields("counter")
.setUpsertRequest(jsonBuilder().startObject().field("counter", 1).endObject())
.setUpsert(jsonBuilder().startObject().field("counter", 1).endObject())
);
}

View File

@ -19,10 +19,9 @@
package org.elasticsearch.test.integration.routing;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.RoutingMissingException;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
import org.elasticsearch.client.Requests;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
@ -66,7 +65,7 @@ public class AliasRoutingTests extends AbstractSharedClusterTest {
logger.info("--> updating with id [1] and routing through alias");
client().prepareUpdate("alias0", "type1", "1")
.setUpsertRequest(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
.setUpsert(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
.setScript("ctx._source.field = 'value2'")
.execute().actionGet();
for (int i = 0; i < 5; i++) {

View File

@ -91,7 +91,7 @@ public class SimpleQueryTests extends AbstractSharedClusterTest {
@Test
public void passQueryAsStringTest() throws Exception {
client().admin().indices().prepareCreate("test").setSettings(ImmutableSettings.settingsBuilder().put("index.number_of_shards", 1)).execute().actionGet();
client().admin().indices().prepareCreate("test").setSettings("index.number_of_shards", 1).execute().actionGet();
client().prepareIndex("test", "type1", "1").setSource("field1", "value1_1", "field2", "value2_1").setRefresh(true).execute().actionGet();
@ -102,16 +102,16 @@ public class SimpleQueryTests extends AbstractSharedClusterTest {
@Test
public void testIndexOptions() throws Exception {
client().admin().indices().prepareCreate("test")
.addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("field1").field("index_options", "docs").field("type", "string").endObject().endObject().endObject().endObject())
.setSettings(ImmutableSettings.settingsBuilder().put("index.number_of_shards", 1)).execute().actionGet();
.addMapping("type1", "field1", "type=string,index_options=docs")
.setSettings("index.number_of_shards", 1).get();
client().prepareIndex("test", "type1", "1").setSource("field1", "quick brown fox", "field2", "quick brown fox").execute().actionGet();
client().prepareIndex("test", "type1", "2").setSource("field1", "quick lazy huge brown fox", "field2", "quick lazy huge brown fox").setRefresh(true).execute().actionGet();
SearchResponse searchResponse = client().prepareSearch().setQuery(QueryBuilders.matchQuery("field2", "quick brown").type(MatchQueryBuilder.Type.PHRASE).slop(0)).execute().actionGet();
SearchResponse searchResponse = client().prepareSearch().setQuery(QueryBuilders.matchQuery("field2", "quick brown").type(MatchQueryBuilder.Type.PHRASE).slop(0)).get();
assertThat(searchResponse.getHits().totalHits(), equalTo(1l));
try {
client().prepareSearch().setQuery(QueryBuilders.matchQuery("field1", "quick brown").type(MatchQueryBuilder.Type.PHRASE).slop(0)).execute().actionGet();
client().prepareSearch().setQuery(QueryBuilders.matchQuery("field1", "quick brown").type(MatchQueryBuilder.Type.PHRASE).slop(0)).get();
} catch (SearchPhaseExecutionException e) {
assertTrue(e.getMessage().endsWith("IllegalStateException[field \"field1\" was indexed without position data; cannot run PhraseQuery (term=quick)]; }"));
}
@ -120,7 +120,7 @@ public class SimpleQueryTests extends AbstractSharedClusterTest {
@Test
public void testCommonTermsQuery() throws Exception {
client().admin().indices().prepareCreate("test")
.addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("field1").field("analyzer", "whitespace").field("type", "string").endObject().endObject().endObject().endObject())
.addMapping("type1", "field1", "type=string,analyzer=whitespace")
.setSettings(ImmutableSettings.settingsBuilder().put("index.number_of_shards", 1)).execute().actionGet();
client().prepareIndex("test", "type1", "1").setSource("field1", "the quick brown fox").execute().actionGet();
@ -206,11 +206,11 @@ public class SimpleQueryTests extends AbstractSharedClusterTest {
public void testOmitTermFreqsAndPositions() throws Exception {
// backwards compat test!
client().admin().indices().prepareCreate("test")
.addMapping("type1", jsonBuilder().startObject().startObject("type1").startObject("properties").startObject("field1").field("omit_term_freq_and_positions", true).field("type", "string").endObject().endObject().endObject().endObject())
.setSettings(ImmutableSettings.settingsBuilder().put("index.number_of_shards", 1)).execute().actionGet();
.addMapping("type1", "field1", "type=string,omit_term_freq_and_positions=true")
.setSettings(ImmutableSettings.settingsBuilder().put("index.number_of_shards", 1)).get();
client().prepareIndex("test", "type1", "1").setSource("field1", "quick brown fox", "field2", "quick brown fox").execute().actionGet();
client().prepareIndex("test", "type1", "2").setSource("field1", "quick lazy huge brown fox", "field2", "quick lazy huge brown fox").setRefresh(true).execute().actionGet();
client().prepareIndex("test", "type1", "1").setSource("field1", "quick brown fox", "field2", "quick brown fox").get();
client().prepareIndex("test", "type1", "2").setSource("field1", "quick lazy huge brown fox", "field2", "quick lazy huge brown fox").setRefresh(true).get();
SearchResponse searchResponse = client().prepareSearch().setQuery(QueryBuilders.matchQuery("field2", "quick brown").type(MatchQueryBuilder.Type.PHRASE).slop(0)).execute().actionGet();

View File

@ -139,7 +139,7 @@ public class UpdateTests extends AbstractSharedClusterTest {
ensureGreen();
UpdateResponse updateResponse = client().prepareUpdate("test", "type1", "1")
.setUpsertRequest(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
.setUpsert(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
.setScript("ctx._source.field += 1")
.execute().actionGet();
assertTrue(updateResponse.isCreated());
@ -150,7 +150,7 @@ public class UpdateTests extends AbstractSharedClusterTest {
}
updateResponse = client().prepareUpdate("test", "type1", "1")
.setUpsertRequest(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
.setUpsert(XContentFactory.jsonBuilder().startObject().field("field", 1).endObject())
.setScript("ctx._source.field += 1")
.execute().actionGet();
assertFalse(updateResponse.isCreated());
@ -195,7 +195,7 @@ public class UpdateTests extends AbstractSharedClusterTest {
ensureGreen();
UpdateResponse updateResponse = client().prepareUpdate("test", "type1", "1")
.setUpsertRequest(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
.setUpsert(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
.setScript("ctx._source.extra = \"foo\"")
.setFields("_source")
.execute().actionGet();
@ -205,7 +205,7 @@ public class UpdateTests extends AbstractSharedClusterTest {
assertThat(updateResponse.getGetResult().sourceAsMap().get("extra"), nullValue());
updateResponse = client().prepareUpdate("test", "type1", "1")
.setUpsertRequest(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
.setUpsert(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
.setScript("ctx._source.extra = \"foo\"")
.setFields("_source")
.execute().actionGet();
@ -250,14 +250,14 @@ public class UpdateTests extends AbstractSharedClusterTest {
// upserts - the combination with versions is a bit weird. Test are here to ensure we do not change our behavior unintentionally
// With internal versions, tt means "if object is there with version X, update it or explode. If it is not there, index.
run(client().prepareUpdate("test", "type", "3").setScript("ctx._source.text = 'v2'").setVersion(10).setUpsertRequest("{ \"text\": \"v0\" }"));
run(client().prepareUpdate("test", "type", "3").setScript("ctx._source.text = 'v2'").setVersion(10).setUpsert("{ \"text\": \"v0\" }"));
GetResponse get = get("test", "type", "3");
assertThat(get.getVersion(), equalTo(1l));
assertThat((String) get.getSource().get("text"), equalTo("v0"));
// With external versions, it means - if object is there with version lower than X, update it or explode. If it is not there, insert with new version.
run(client().prepareUpdate("test", "type", "4").setScript("ctx._source.text = 'v2'").
setVersion(10).setVersionType(VersionType.EXTERNAL).setUpsertRequest("{ \"text\": \"v0\" }"));
setVersion(10).setVersionType(VersionType.EXTERNAL).setUpsert("{ \"text\": \"v0\" }"));
get = get("test", "type", "4");
assertThat(get.getVersion(), equalTo(10l));
assertThat((String) get.getSource().get("text"), equalTo("v0"));
@ -272,7 +272,7 @@ public class UpdateTests extends AbstractSharedClusterTest {
@Test
public void testIndexAutoCreation() throws Exception {
UpdateResponse updateResponse = client().prepareUpdate("test", "type1", "1")
.setUpsertRequest(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
.setUpsert(XContentFactory.jsonBuilder().startObject().field("bar", "baz").endObject())
.setScript("ctx._source.extra = \"foo\"")
.setFields("_source")
.execute().actionGet();
@ -486,12 +486,12 @@ public class UpdateTests extends AbstractSharedClusterTest {
UpdateRequestBuilder updateRequestBuilder = client().prepareUpdate("test", "type1", Integer.toString(i))
.setScript("ctx._source.field += 1")
.setRetryOnConflict(Integer.MAX_VALUE)
.setUpsertRequest(jsonBuilder().startObject().field("field", 1).endObject());
.setUpsert(jsonBuilder().startObject().field("field", 1).endObject());
client().prepareBulk().add(updateRequestBuilder).execute().actionGet();
} else {
client().prepareUpdate("test", "type1", Integer.toString(i)).setScript("ctx._source.field += 1")
.setRetryOnConflict(Integer.MAX_VALUE)
.setUpsertRequest(jsonBuilder().startObject().field("field", 1).endObject())
.setUpsert(jsonBuilder().startObject().field("field", 1).endObject())
.execute().actionGet();
}
}