Added ext section to search request for plugins that extend the fetch phase

tested with term vectors fetch
This commit is contained in:
Colin Goodheart-Smithe 2015-09-25 09:01:59 +01:00
parent 78d6d2987f
commit f3b581a6e0
4 changed files with 83 additions and 15 deletions

View File

@ -859,6 +859,36 @@ public class SearchService extends AbstractLifecycleComponent<SearchService> {
context.scriptFields().add(new ScriptField(field.fieldName(), searchScript, false)); // NORELEASE need to have ignore_exception parsed somewhere context.scriptFields().add(new ScriptField(field.fieldName(), searchScript, false)); // NORELEASE need to have ignore_exception parsed somewhere
} }
} }
if (source.ext() != null) {
XContentParser extParser = null;
try {
extParser = XContentFactory.xContent(source.ext()).createParser(source.ext());
XContentParser.Token token = extParser.nextToken();
String currentFieldName = null;
while ((token = extParser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentFieldName = extParser.currentName();
} else {
SearchParseElement parseElement = this.elementParsers.get(currentFieldName);
if (parseElement == null) {
throw new SearchParseException(context, "Unknown element [" + currentFieldName + "] in [ext]",
extParser.getTokenLocation());
} else {
parseElement.parse(extParser, context);
}
}
}
} catch (Exception e) {
String sSource = "_na_";
try {
sSource = source.toString();
} catch (Throwable e1) {
// ignore
}
XContentLocation location = extParser != null ? extParser.getTokenLocation() : null;
throw new SearchParseException(context, "failed to parse ext source [" + sSource + "]", location, e);
}
}
// NOCOMMIT need to work out what to do about term_vectors_fetch (previously handled by TermVectorsFetchParseElement) as this is not available as an option in SearchSourceBuilder // NOCOMMIT need to work out what to do about term_vectors_fetch (previously handled by TermVectorsFetchParseElement) as this is not available as an option in SearchSourceBuilder
if (source.version() != null) { if (source.version() != null) {
context.version(source.version()); context.version(source.version());

View File

@ -93,6 +93,7 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
public static final ParseField SUGGEST_FIELD = new ParseField("suggest"); public static final ParseField SUGGEST_FIELD = new ParseField("suggest");
public static final ParseField RESCORE_FIELD = new ParseField("rescore"); public static final ParseField RESCORE_FIELD = new ParseField("rescore");
public static final ParseField STATS_FIELD = new ParseField("stats"); public static final ParseField STATS_FIELD = new ParseField("stats");
public static final ParseField EXT_FIELD = new ParseField("ext");
public static final SearchSourceBuilder PROTOTYPE = new SearchSourceBuilder(); public static final SearchSourceBuilder PROTOTYPE = new SearchSourceBuilder();
@ -151,6 +152,8 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
private String[] stats; private String[] stats;
private BytesReference ext = null;
/** /**
* Constructs a new search source builder. * Constructs a new search source builder.
*/ */
@ -681,6 +684,15 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
return stats; return stats;
} }
public SearchSourceBuilder ext(XContentBuilder ext) {
this.ext = ext.bytes();
return this;
}
public BytesReference ext() {
return ext;
}
public SearchSourceBuilder fromXContent(XContentParser parser, QueryParseContext context) throws IOException { public SearchSourceBuilder fromXContent(XContentParser parser, QueryParseContext context) throws IOException {
SearchSourceBuilder builder = new SearchSourceBuilder(); SearchSourceBuilder builder = new SearchSourceBuilder();
XContentParser.Token token; XContentParser.Token token;
@ -812,6 +824,9 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
XContentBuilder xContentBuilder = XContentFactory.contentBuilder(parser.contentType()).copyCurrentStructure(parser); XContentBuilder xContentBuilder = XContentFactory.contentBuilder(parser.contentType()).copyCurrentStructure(parser);
sorts.add(xContentBuilder.bytes()); sorts.add(xContentBuilder.bytes());
builder.sorts = sorts; builder.sorts = sorts;
} else if (context.parseFieldMatcher().match(currentFieldName, EXT_FIELD)) {
XContentBuilder xContentBuilder = XContentFactory.contentBuilder(parser.contentType()).copyCurrentStructure(parser);
builder.ext = xContentBuilder.bytes();
} else { } else {
throw new ParsingException(parser.getTokenLocation(), "Unknown key for a " + token + " in [" + currentFieldName + "].", throw new ParsingException(parser.getTokenLocation(), "Unknown key for a " + token + " in [" + currentFieldName + "].",
parser.getTokenLocation()); parser.getTokenLocation());
@ -1031,6 +1046,13 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
if (stats != null) { if (stats != null) {
builder.array(STATS_FIELD.getPreferredName(), stats); builder.array(STATS_FIELD.getPreferredName(), stats);
} }
if (ext != null) {
builder.field(EXT_FIELD.getPreferredName());
XContentParser parser = XContentFactory.xContent(XContentType.JSON).createParser(ext);
parser.nextToken();
builder.copyCurrentStructure(parser);
}
} }
public static class ScriptField implements Writeable<ScriptField>, ToXContent { public static class ScriptField implements Writeable<ScriptField>, ToXContent {
@ -1184,6 +1206,9 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
builder.timeoutInMillis = in.readLong(); builder.timeoutInMillis = in.readLong();
builder.trackScores = in.readBoolean(); builder.trackScores = in.readBoolean();
builder.version = in.readOptionalBoolean(); builder.version = in.readOptionalBoolean();
if (in.readBoolean()) {
builder.ext = in.readBytesReference();
}
return builder; return builder;
} }
@ -1294,6 +1319,11 @@ public final class SearchSourceBuilder extends ToXContentToBytes implements Writ
out.writeLong(timeoutInMillis); out.writeLong(timeoutInMillis);
out.writeBoolean(trackScores); out.writeBoolean(trackScores);
out.writeOptionalBoolean(version); out.writeOptionalBoolean(version);
boolean hasExt = ext != null;
out.writeBoolean(hasExt);
if (hasExt) {
out.writeBytesReference(ext);
}
} }
@Override @Override

View File

@ -45,6 +45,7 @@ import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.settings.SettingsModule; import org.elasticsearch.common.settings.SettingsModule;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory; import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.env.Environment; import org.elasticsearch.env.Environment;
@ -414,6 +415,14 @@ public class NewSearchSourceBuilderTests extends ESTestCase {
// NORELEASE need a random aggregation builder method // NORELEASE need a random aggregation builder method
builder.aggregation(AggregationBuilders.avg(randomAsciiOfLengthBetween(5, 20))); builder.aggregation(AggregationBuilders.avg(randomAsciiOfLengthBetween(5, 20)));
} }
if (true) {
// NORELEASE need a method to randomly build content for ext
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder();
xContentBuilder.startObject();
xContentBuilder.field("term_vectors_fetch", randomAsciiOfLengthBetween(5, 20));
xContentBuilder.endObject();
builder.ext(xContentBuilder);
}
return builder; return builder;
} }

View File

@ -24,14 +24,17 @@ import com.google.common.collect.ImmutableMap;
import org.apache.lucene.index.PostingsEnum; import org.apache.lucene.index.PostingsEnum;
import org.apache.lucene.index.TermsEnum; import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.BytesRef;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.termvectors.TermVectorsRequest; import org.elasticsearch.action.termvectors.TermVectorsRequest;
import org.elasticsearch.action.termvectors.TermVectorsResponse; import org.elasticsearch.action.termvectors.TermVectorsResponse;
import org.elasticsearch.common.Priority; import org.elasticsearch.common.Priority;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.plugins.Plugin; import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.search.SearchHitField; import org.elasticsearch.search.SearchHitField;
import org.elasticsearch.search.SearchModule; import org.elasticsearch.search.SearchModule;
import org.elasticsearch.search.SearchParseElement; import org.elasticsearch.search.SearchParseElement;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.internal.InternalSearchHit; import org.elasticsearch.search.internal.InternalSearchHit;
import org.elasticsearch.search.internal.InternalSearchHitField; import org.elasticsearch.search.internal.InternalSearchHitField;
import org.elasticsearch.search.internal.SearchContext; import org.elasticsearch.search.internal.SearchContext;
@ -48,6 +51,8 @@ import java.util.Map;
import static org.elasticsearch.client.Requests.indexRequest; import static org.elasticsearch.client.Requests.indexRequest;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertSearchResponse;
import static org.hamcrest.CoreMatchers.equalTo;
/** /**
* *
@ -83,22 +88,16 @@ public class FetchSubPhasePluginIT extends ESIntegTestCase {
client().admin().indices().prepareRefresh().execute().actionGet(); client().admin().indices().prepareRefresh().execute().actionGet();
String searchSource = jsonBuilder().startObject() XContentBuilder extSource = jsonBuilder().startObject()
.field("term_vectors_fetch", "test") .field("term_vectors_fetch", "test")
.endObject().string(); .endObject();
// SearchResponse response = client().prepareSearch().setSource(new SearchResponse response = client().prepareSearch().setSource(new SearchSourceBuilder().ext(extSource)).get();
// BytesArray(searchSource)).get(); assertSearchResponse(response);
// assertSearchResponse(response); assertThat(((Map<String, Integer>) response.getHits().getAt(0).field("term_vectors_fetch").getValues().get(0)).get("i"), equalTo(2));
// assertThat(((Map<String, Integer>) assertThat(((Map<String, Integer>) response.getHits().getAt(0).field("term_vectors_fetch").getValues().get(0)).get("am"),
// response.getHits().getAt(0).field("term_vectors_fetch").getValues().get(0)).get("i"), equalTo(2));
// equalTo(2)); assertThat(((Map<String, Integer>) response.getHits().getAt(0).field("term_vectors_fetch").getValues().get(0)).get("sam"),
// assertThat(((Map<String, Integer>) equalTo(1));
// response.getHits().getAt(0).field("term_vectors_fetch").getValues().get(0)).get("am"),
// equalTo(2));
// assertThat(((Map<String, Integer>)
// response.getHits().getAt(0).field("term_vectors_fetch").getValues().get(0)).get("sam"),
// equalTo(1));
// NOCOMMIT fix this
} }
public static class FetchTermVectorsPlugin extends Plugin { public static class FetchTermVectorsPlugin extends Plugin {