Term Vectors: support for version and version_type

This commit adds support for version and version_type to the Term Vectors API.
This could be useful in the following case whereby the user gets a document
and later wants to generate its TVs. With version, this would ensure that only
the TVs of that particular document are generated, and error out if the
document has been updated in between.

Closes #7480
This commit is contained in:
Alex Ksikes 2014-08-27 13:22:20 +02:00
parent c2695d3d77
commit 86e1655e4b
11 changed files with 457 additions and 32 deletions

View File

@ -72,9 +72,18 @@
"required" : false
},
"realtime": {
"type" : "boolean",
"description" : "Specifies if requests are real-time as opposed to near-real-time (default: true).",
"required" : false
"type": "boolean",
"description": "Specifies if requests are real-time as opposed to near-real-time (default: true).",
"required": false
},
"version" : {
"type" : "number",
"description" : "Explicit version number for concurrency control"
},
"version_type": {
"type" : "enum",
"options" : ["internal", "external", "external_gte", "force"],
"description" : "Specific version type"
}
}
},

View File

@ -79,9 +79,18 @@
"required" : false
},
"realtime": {
"type" : "boolean",
"description" : "Specifies if request is real-time as opposed to near-real-time (default: true).",
"required" : false
"type": "boolean",
"description": "Specifies if request is real-time as opposed to near-real-time (default: true).",
"required": false
},
"version" : {
"type" : "number",
"description" : "Explicit version number for concurrency control"
},
"version_type": {
"type" : "enum",
"options" : ["internal", "external", "external_gte", "force"],
"description" : "Specific version type"
}
}
},

View File

@ -0,0 +1,115 @@
---
"Versions":
- do:
index:
index: test_1
type: test
id: 1
body: { foo: bar }
- match: { _version: 1}
- do:
index:
index: test_1
type: test
id: 1
body: { foo: bar }
- match: { _version: 2}
- do:
get:
index: test_1
type: test
id: 1
version: 2
- match: { _id: "1" }
- do:
catch: conflict
get:
index: test_1
type: test
id: 1
version: 1
- do:
get:
index: test_1
type: test
id: 1
version: 2
version_type: external
- match: { _id: "1" }
- do:
catch: conflict
get:
index: test_1
type: test
id: 1
version: 10
version_type: external
- do:
catch: conflict
get:
index: test_1
type: test
id: 1
version: 1
version_type: external
- do:
get:
index: test_1
type: test
id: 1
version: 2
version_type: external_gte
- match: { _id: "1" }
- do:
catch: conflict
get:
index: test_1
type: test
id: 1
version: 10
version_type: external_gte
- do:
catch: conflict
get:
index: test_1
type: test
id: 1
version: 1
version_type: external_gte
- do:
get:
index: test_1
type: test
id: 1
version: 2
version_type: force
- match: { _id: "1" }
- do:
get:
index: test_1
type: test
id: 1
version: 10
version_type: force
- match: { _id: "1" }
- do:
get:
index: test_1
type: test
id: 1
version: 1
version_type: force
- match: { _id: "1" }

View File

@ -23,7 +23,6 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.DocumentRequest;
import org.elasticsearch.action.ValidateActions;
@ -32,8 +31,10 @@ import org.elasticsearch.action.support.single.shard.SingleShardOperationRequest
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.VersionType;
import java.io.IOException;
import java.util.*;
@ -58,6 +59,10 @@ public class TermVectorsRequest extends SingleShardOperationRequest<TermVectorsR
private String routing;
private VersionType versionType = VersionType.INTERNAL;
private long version = Versions.MATCH_ANY;
protected String preference;
private static final AtomicInteger randomInt = new AtomicInteger(0);
@ -355,6 +360,24 @@ public class TermVectorsRequest extends SingleShardOperationRequest<TermVectorsR
return this;
}
public long version() {
return version;
}
public TermVectorsRequest version(long version) {
this.version = version;
return this;
}
public VersionType versionType() {
return versionType;
}
public TermVectorsRequest versionType(VersionType versionType) {
this.versionType = versionType;
return this;
}
private void setFlag(Flag flag, boolean set) {
if (set && !flagsEnum.contains(flag)) {
flagsEnum.add(flag);
@ -412,7 +435,9 @@ public class TermVectorsRequest extends SingleShardOperationRequest<TermVectorsR
if (in.readBoolean()) {
perFieldAnalyzer = readPerFieldAnalyzer(in.readMap());
}
this.realtime = in.readBoolean();
realtime = in.readBoolean();
versionType = VersionType.fromValue(in.readByte());
version = in.readLong();
}
@Override
@ -445,6 +470,8 @@ public class TermVectorsRequest extends SingleShardOperationRequest<TermVectorsR
out.writeGenericValue(perFieldAnalyzer);
}
out.writeBoolean(realtime());
out.writeByte(versionType.getValue());
out.writeLong(version);
}
public static enum Flag {
@ -503,6 +530,10 @@ public class TermVectorsRequest extends SingleShardOperationRequest<TermVectorsR
termVectorsRequest.doc(jsonBuilder().copyCurrentStructure(parser));
} else if ("_routing".equals(currentFieldName) || "routing".equals(currentFieldName)) {
termVectorsRequest.routing = parser.text();
} else if ("_version".equals(currentFieldName) || "version".equals(currentFieldName)) {
termVectorsRequest.version = parser.longValue();
} else if ("_version_type".equals(currentFieldName) || "_versionType".equals(currentFieldName) || "version_type".equals(currentFieldName) || "versionType".equals(currentFieldName)) {
termVectorsRequest.versionType = VersionType.fromString(parser.text());
} else {
throw new ElasticsearchParseException("The parameter " + currentFieldName
+ " is not valid for term vector request!");

View File

@ -23,6 +23,7 @@ import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.ActionRequestBuilder;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.index.VersionType;
import java.util.Map;
@ -174,6 +175,23 @@ public class TermVectorsRequestBuilder extends ActionRequestBuilder<TermVectorsR
return this;
}
/*
* Sets the version, which will cause the get operation to only be performed if a matching
* version exists and no changes happened on the doc since then.
*/
public TermVectorsRequestBuilder setVersion(long version) {
request.version(version);
return this;
}
/*
* Sets the versioning type. Defaults to {@link org.elasticsearch.index.VersionType#INTERNAL}.
*/
public TermVectorsRequestBuilder setVersionType(VersionType versionType) {
request.versionType(versionType);
return this;
}
/**
* Sets the analyzer used at each field when generating term vectors.
*/

View File

@ -347,6 +347,10 @@ public class TermVectorsResponse extends ActionResponse implements ToXContent {
}
public Long getVersion() {
return docVersion;
}
public String getIndex() {
return index;
}

View File

@ -77,12 +77,11 @@ public class ShardTermVectorsService extends AbstractIndexShardComponent {
}
public TermVectorsResponse getTermVectors(TermVectorsRequest request, String concreteIndex) {
final Engine.Searcher searcher = indexShard.acquireSearcher("term_vector");
IndexReader topLevelReader = searcher.reader();
final TermVectorsResponse termVectorsResponse = new TermVectorsResponse(concreteIndex, request.type(), request.id());
final Term uidTerm = new Term(UidFieldMapper.NAME, Uid.createUidAsBytes(request.type(), request.id()));
Engine.GetResult get = indexShard.get(new Engine.Get(request.realtime(), uidTerm));
Engine.GetResult get = indexShard.get(new Engine.Get(request.realtime(), uidTerm).version(request.version()).versionType(request.versionType()));
boolean docFromTranslog = get.source() != null;
AggregatedDfs dfs = null;
@ -97,8 +96,9 @@ public class ShardTermVectorsService extends AbstractIndexShardComponent {
handleFieldWildcards(request);
}
final Engine.Searcher searcher = indexShard.acquireSearcher("term_vector");
try {
Fields topLevelFields = MultiFields.getFields(topLevelReader);
Fields topLevelFields = MultiFields.getFields(get.searcher() != null ? get.searcher().reader() : searcher.reader());
Versions.DocIdAndVersion docIdAndVersion = get.docIdAndVersion();
/* from an artificial document */
if (request.doc() != null) {

View File

@ -50,6 +50,11 @@ public class RestActions {
return Versions.MATCH_ANY;
}
public static long parseVersion(RestRequest request, long defaultVersion) {
long version = parseVersion(request);
return (version == Versions.MATCH_ANY) ? defaultVersion : version;
}
static final class Fields {
static final XContentBuilderString _SHARDS = new XContentBuilderString("_shards");
static final XContentBuilderString TOTAL = new XContentBuilderString("total");

View File

@ -27,7 +27,12 @@ import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.rest.*;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestChannel;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.support.RestActions;
import org.elasticsearch.rest.action.support.RestToXContentListener;
import java.util.HashSet;
@ -84,6 +89,8 @@ public class RestTermVectorsAction extends BaseRestHandler {
termVectorsRequest.payloads(request.paramAsBoolean("payloads", termVectorsRequest.payloads()));
termVectorsRequest.routing(request.param("routing"));
termVectorsRequest.realtime(request.paramAsBoolean("realtime", null));
termVectorsRequest.version(RestActions.parseVersion(request, termVectorsRequest.version()));
termVectorsRequest.versionType(VersionType.fromString(request.param("version_type"), termVectorsRequest.versionType()));
termVectorsRequest.parent(request.param("parent"));
termVectorsRequest.preference(request.param("preference"));
termVectorsRequest.termStatistics(request.paramAsBoolean("termStatistics", termVectorsRequest.termStatistics()));

View File

@ -33,6 +33,7 @@ import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.index.engine.VersionConflictEngineException;
import org.elasticsearch.index.mapper.core.AbstractFieldMapper;
import org.hamcrest.Matcher;
import org.junit.Test;
@ -669,15 +670,10 @@ public class GetTermVectorsTests extends AbstractTermVectorsTests {
public void testDuelWithAndWithoutTermVectors() throws ElasticsearchException, IOException, ExecutionException, InterruptedException {
// setup indices
String[] indexNames = new String[] {"with_tv", "without_tv"};
ImmutableSettings.Builder settings = settingsBuilder()
.put(indexSettings())
.put("index.analysis.analyzer", "standard");
assertAcked(prepareCreate(indexNames[0])
.setSettings(settings)
.addMapping("type1", "field1", "type=string,term_vector=with_positions_offsets"));
.addMapping("type1", "field1", "type=string,term_vector=with_positions_offsets,analyzer=keyword"));
assertAcked(prepareCreate(indexNames[1])
.setSettings(settings)
.addMapping("type1", "field1", "type=string,term_vector=no"));
.addMapping("type1", "field1", "type=string,term_vector=no,analyzer=keyword"));
ensureGreen();
// index documents with and without term vectors
@ -691,29 +687,28 @@ public class GetTermVectorsTests extends AbstractTermVectorsTests {
"Transforming a data stream (such as when using a scrambler in telecommunications)."};
List<IndexRequestBuilder> indexBuilders = new ArrayList<>();
for (int i = 0; i < content.length; i++) {
for (String indexName : indexNames) {
for (String indexName : indexNames) {
for (int id = 0; id < content.length; id++) {
indexBuilders.add(client().prepareIndex()
.setIndex(indexName)
.setType("type1")
.setId(String.valueOf(i))
.setSource("field1", content[i]));
.setId(String.valueOf(id))
.setSource("field1", content[id]));
}
}
indexRandom(true, indexBuilders);
// request tvs and compare from each index
for (int i = 0; i < content.length; i++) {
for (int id = 0; id < content.length; id++) {
Fields[] fields = new Fields[2];
int idx = 0;
for (String indexName : indexNames) {
TermVectorsResponse resp = client().prepareTermVectors(indexName, "type1", String.valueOf(i))
for (int j = 0; j < indexNames.length; j++) {
TermVectorsResponse resp = client().prepareTermVector(indexNames[j], "type1", String.valueOf(id))
.setOffsets(true)
.setPositions(true)
.setSelectedFields("field1")
.get();
assertThat("doc with index: test_with_tv, type1 and id: " + i, resp.isExists(), equalTo(true));
fields[idx++] = resp.getFields();
assertThat("doc with index: " + indexNames[j] + ", type1 and id: " + id, resp.isExists(), equalTo(true));
fields[j] = resp.getFields();
}
compareTermVectors("field1", fields[0], fields[1]);
}
@ -1126,4 +1121,107 @@ public class GetTermVectorsTests extends AbstractTermVectorsTests {
return lessThan(value);
}
@Test
public void testTermVectorsWithVersion() {
assertAcked(prepareCreate("test").addAlias(new Alias("alias"))
.setSettings(ImmutableSettings.settingsBuilder().put("index.refresh_interval", -1)));
ensureGreen();
TermVectorsResponse response = client().prepareTermVectors("test", "type1", "1").get();
assertThat(response.isExists(), equalTo(false));
logger.info("--> index doc 1");
client().prepareIndex("test", "type1", "1").setSource("field1", "value1", "field2", "value2").get();
// From translog:
// version 0 means ignore version, which is the default
response = client().prepareTermVectors(indexOrAlias(), "type1", "1").setVersion(0).get();
assertThat(response.isExists(), equalTo(true));
assertThat(response.getId(), equalTo("1"));
assertThat(response.getVersion(), equalTo(1l));
response = client().prepareTermVectors(indexOrAlias(), "type1", "1").setVersion(1).get();
assertThat(response.isExists(), equalTo(true));
assertThat(response.getId(), equalTo("1"));
assertThat(response.getVersion(), equalTo(1l));
try {
client().prepareGet(indexOrAlias(), "type1", "1").setVersion(2).get();
fail();
} catch (VersionConflictEngineException e) {
//all good
}
// From Lucene index:
refresh();
// version 0 means ignore version, which is the default
response = client().prepareTermVectors(indexOrAlias(), "type1", "1").setVersion(0).setRealtime(false).get();
assertThat(response.isExists(), equalTo(true));
assertThat(response.getId(), equalTo("1"));
assertThat(response.getIndex(), equalTo("test"));
assertThat(response.getVersion(), equalTo(1l));
response = client().prepareTermVectors(indexOrAlias(), "type1", "1").setVersion(1).setRealtime(false).get();
assertThat(response.isExists(), equalTo(true));
assertThat(response.getId(), equalTo("1"));
assertThat(response.getIndex(), equalTo("test"));
assertThat(response.getVersion(), equalTo(1l));
try {
client().prepareGet(indexOrAlias(), "type1", "1").setVersion(2).setRealtime(false).get();
fail();
} catch (VersionConflictEngineException e) {
//all good
}
logger.info("--> index doc 1 again, so increasing the version");
client().prepareIndex("test", "type1", "1").setSource("field1", "value1", "field2", "value2").get();
// From translog:
// version 0 means ignore version, which is the default
response = client().prepareTermVectors(indexOrAlias(), "type1", "1").setVersion(0).get();
assertThat(response.isExists(), equalTo(true));
assertThat(response.getId(), equalTo("1"));
assertThat(response.getIndex(), equalTo("test"));
assertThat(response.getVersion(), equalTo(2l));
try {
client().prepareGet(indexOrAlias(), "type1", "1").setVersion(1).get();
fail();
} catch (VersionConflictEngineException e) {
//all good
}
response = client().prepareTermVectors(indexOrAlias(), "type1", "1").setVersion(2).get();
assertThat(response.isExists(), equalTo(true));
assertThat(response.getId(), equalTo("1"));
assertThat(response.getIndex(), equalTo("test"));
assertThat(response.getVersion(), equalTo(2l));
// From Lucene index:
refresh();
// version 0 means ignore version, which is the default
response = client().prepareTermVectors(indexOrAlias(), "type1", "1").setVersion(0).setRealtime(false).get();
assertThat(response.isExists(), equalTo(true));
assertThat(response.getId(), equalTo("1"));
assertThat(response.getIndex(), equalTo("test"));
assertThat(response.getVersion(), equalTo(2l));
try {
client().prepareGet(indexOrAlias(), "type1", "1").setVersion(1).setRealtime(false).get();
fail();
} catch (VersionConflictEngineException e) {
//all good
}
response = client().prepareTermVectors(indexOrAlias(), "type1", "1").setVersion(2).setRealtime(false).get();
assertThat(response.isExists(), equalTo(true));
assertThat(response.getId(), equalTo("1"));
assertThat(response.getIndex(), equalTo("test"));
assertThat(response.getVersion(), equalTo(2l));
}
}

View File

@ -21,9 +21,16 @@ package org.elasticsearch.action.termvectors;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.Fields;
import org.apache.lucene.index.Terms;
import org.apache.lucene.index.TermsEnum;
import org.elasticsearch.action.admin.indices.alias.Alias;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import java.io.IOException;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.*;
public class MultiTermVectorsTests extends AbstractTermVectorsTests {
@ -72,4 +79,126 @@ public class MultiTermVectorsTests extends AbstractTermVectorsTests {
assertThat(response.getResponses().length, equalTo(1));
assertThat(response.getResponses()[0].getFailure().getMessage(), equalTo("[" + response.getResponses()[0].getIndex() + "] missing"));
}
@Test
public void testMultiTermVectorsWithVersion() throws Exception {
assertAcked(prepareCreate("test").addAlias(new Alias("alias"))
.setSettings(ImmutableSettings.settingsBuilder().put("index.refresh_interval", -1)));
ensureGreen();
MultiTermVectorsResponse response = client().prepareMultiTermVectors().add(indexOrAlias(), "type1", "1").get();
assertThat(response.getResponses().length, equalTo(1));
assertThat(response.getResponses()[0].getResponse().isExists(), equalTo(false));
for (int i = 0; i < 3; i++) {
client().prepareIndex("test", "type1", Integer.toString(i)).setSource("field", "value" + i).get();
}
// Version from translog
response = client().prepareMultiTermVectors()
.add(new TermVectorsRequest(indexOrAlias(), "type1", "1").selectedFields("field").version(0))
.add(new TermVectorsRequest(indexOrAlias(), "type1", "1").selectedFields("field").version(1))
.add(new TermVectorsRequest(indexOrAlias(), "type1", "1").selectedFields("field").version(2))
.get();
assertThat(response.getResponses().length, equalTo(3));
// [0] version doesn't matter, which is the default
assertThat(response.getResponses()[0].getFailure(), nullValue());
assertThat(response.getResponses()[0].getId(), equalTo("1"));
assertThat(response.getResponses()[0].getIndex(), equalTo("test"));
assertThat(response.getResponses()[0].getResponse().isExists(), equalTo(true));
checkTermTexts(response.getResponses()[0].getResponse().getFields().terms("field"), new String[]{"value1"});
assertThat(response.getResponses()[1].getId(), equalTo("1"));
assertThat(response.getResponses()[1].getIndex(), equalTo("test"));
assertThat(response.getResponses()[1].getFailure(), nullValue());
assertThat(response.getResponses()[1].getResponse().isExists(), equalTo(true));
checkTermTexts(response.getResponses()[1].getResponse().getFields().terms("field"), new String[]{"value1"});
assertThat(response.getResponses()[2].getFailure(), notNullValue());
assertThat(response.getResponses()[2].getFailure().getId(), equalTo("1"));
assertThat(response.getResponses()[2].getFailure().getMessage(), startsWith("VersionConflictEngineException"));
//Version from Lucene index
refresh();
response = client().prepareMultiTermVectors()
.add(new TermVectorsRequest(indexOrAlias(), "type1", "1").selectedFields("field").version(0).realtime(false))
.add(new TermVectorsRequest(indexOrAlias(), "type1", "1").selectedFields("field").version(1).realtime(false))
.add(new TermVectorsRequest(indexOrAlias(), "type1", "1").selectedFields("field").version(2).realtime(false))
.get();
assertThat(response.getResponses().length, equalTo(3));
// [0] version doesn't matter, which is the default
assertThat(response.getResponses()[0].getFailure(), nullValue());
assertThat(response.getResponses()[0].getId(), equalTo("1"));
assertThat(response.getResponses()[0].getResponse().isExists(), equalTo(true));
checkTermTexts(response.getResponses()[0].getResponse().getFields().terms("field"), new String[]{"value1"});
assertThat(response.getResponses()[1].getId(), equalTo("1"));
assertThat(response.getResponses()[1].getFailure(), nullValue());
assertThat(response.getResponses()[1].getResponse().isExists(), equalTo(true));
checkTermTexts(response.getResponses()[1].getResponse().getFields().terms("field"), new String[]{"value1"});
assertThat(response.getResponses()[2].getFailure(), notNullValue());
assertThat(response.getResponses()[2].getFailure().getId(), equalTo("1"));
assertThat(response.getResponses()[2].getFailure().getMessage(), startsWith("VersionConflictEngineException"));
for (int i = 0; i < 3; i++) {
client().prepareIndex("test", "type1", Integer.toString(i)).setSource("field", "value" + i).get();
}
// Version from translog
response = client().prepareMultiTermVectors()
.add(new TermVectorsRequest(indexOrAlias(), "type1", "2").selectedFields("field").version(0))
.add(new TermVectorsRequest(indexOrAlias(), "type1", "2").selectedFields("field").version(1))
.add(new TermVectorsRequest(indexOrAlias(), "type1", "2").selectedFields("field").version(2))
.get();
assertThat(response.getResponses().length, equalTo(3));
// [0] version doesn't matter, which is the default
assertThat(response.getResponses()[0].getFailure(), nullValue());
assertThat(response.getResponses()[0].getId(), equalTo("2"));
assertThat(response.getResponses()[0].getIndex(), equalTo("test"));
assertThat(response.getResponses()[0].getResponse().isExists(), equalTo(true));
checkTermTexts(response.getResponses()[0].getResponse().getFields().terms("field"), new String[]{"value2"});
assertThat(response.getResponses()[1].getFailure(), notNullValue());
assertThat(response.getResponses()[1].getFailure().getId(), equalTo("2"));
assertThat(response.getResponses()[1].getIndex(), equalTo("test"));
assertThat(response.getResponses()[1].getFailure().getMessage(), startsWith("VersionConflictEngineException"));
assertThat(response.getResponses()[2].getId(), equalTo("2"));
assertThat(response.getResponses()[2].getIndex(), equalTo("test"));
assertThat(response.getResponses()[2].getFailure(), nullValue());
assertThat(response.getResponses()[2].getResponse().isExists(), equalTo(true));
checkTermTexts(response.getResponses()[2].getResponse().getFields().terms("field"), new String[]{"value2"});
//Version from Lucene index
refresh();
response = client().prepareMultiTermVectors()
.add(new TermVectorsRequest(indexOrAlias(), "type1", "2").selectedFields("field").version(0))
.add(new TermVectorsRequest(indexOrAlias(), "type1", "2").selectedFields("field").version(1))
.add(new TermVectorsRequest(indexOrAlias(), "type1", "2").selectedFields("field").version(2))
.get();
assertThat(response.getResponses().length, equalTo(3));
// [0] version doesn't matter, which is the default
assertThat(response.getResponses()[0].getFailure(), nullValue());
assertThat(response.getResponses()[0].getId(), equalTo("2"));
assertThat(response.getResponses()[0].getIndex(), equalTo("test"));
assertThat(response.getResponses()[0].getResponse().isExists(), equalTo(true));
checkTermTexts(response.getResponses()[0].getResponse().getFields().terms("field"), new String[]{"value2"});
assertThat(response.getResponses()[1].getFailure(), notNullValue());
assertThat(response.getResponses()[1].getFailure().getId(), equalTo("2"));
assertThat(response.getResponses()[1].getIndex(), equalTo("test"));
assertThat(response.getResponses()[1].getFailure().getMessage(), startsWith("VersionConflictEngineException"));
assertThat(response.getResponses()[2].getId(), equalTo("2"));
assertThat(response.getResponses()[2].getIndex(), equalTo("test"));
assertThat(response.getResponses()[2].getFailure(), nullValue());
assertThat(response.getResponses()[2].getResponse().isExists(), equalTo(true));
checkTermTexts(response.getResponses()[2].getResponse().getFields().terms("field"), new String[]{"value2"});
}
private static String indexOrAlias() {
return randomBoolean() ? "test" : "alias";
}
private void checkTermTexts(Terms terms, String[] expectedTexts) throws IOException {
final TermsEnum termsEnum = terms.iterator(null);
for (String expectedText : expectedTexts) {
assertThat(termsEnum.next().utf8ToString(), equalTo(expectedText));
}
}
}