Support specifying multiple templates (#22139)

Problem: We introduced the ability to shorten the rank eval request by using a
template in #20231. When playing with the API it turned out that there might be
use cases where - e.g. due to various heuristics - folks might want to translate
the original user query into more than just one type of Elasticsearch query.

Solution: Give each template an id that can later be referenced in the
actual requests.

Closes #21257
This commit is contained in:
Isabel Drost-Fromm 2016-12-19 12:49:15 +01:00 committed by GitHub
parent b1e0d698ac
commit bdc32be8b7
9 changed files with 185 additions and 71 deletions

View File

@ -80,12 +80,14 @@ GET /twitter/tweet/_rank_eval
--------------------------------
GET /twitter/tweet/_rank_eval
{
"templates": [{
"id": "match_query",
"template": {
"inline": {
"query": {
"match": {
"{{field}}": {
"query": "{{query_string}}"}}}}}, <1>
"query": "{{query_string}}"}}}}}}], <1>
"requests": [
{
"id": "JFK query",
@ -105,7 +107,8 @@ GET /twitter/tweet/_rank_eval
"params": {
"query_string": "JFK", <2>
"field": "opening_text" <2>
}
},
"template_id": "match_query"
}],
"metric": {
"precision": {

View File

@ -20,7 +20,6 @@
package org.elasticsearch.index.rankeval;
import org.elasticsearch.action.support.ToXContentToBytes;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.io.stream.StreamInput;
@ -34,6 +33,9 @@ import org.elasticsearch.script.Script;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
/**
@ -49,10 +51,9 @@ public class RankEvalSpec extends ToXContentToBytes implements Writeable {
/** Definition of the quality metric, e.g. precision at N */
private RankedListQualityMetric metric;
/** optional: Template to base test requests on */
@Nullable
private Script template;
private Map<String, Script> templates = new HashMap<>();
public RankEvalSpec(Collection<RatedRequest> ratedRequests, RankedListQualityMetric metric, Script template) {
public RankEvalSpec(Collection<RatedRequest> ratedRequests, RankedListQualityMetric metric, Collection<ScriptWithId> templates) {
if (ratedRequests == null || ratedRequests.size() < 1) {
throw new IllegalStateException(
"Cannot evaluate ranking if no search requests with rated results are provided. Seen: " + ratedRequests);
@ -61,7 +62,7 @@ public class RankEvalSpec extends ToXContentToBytes implements Writeable {
throw new IllegalStateException(
"Cannot evaluate ranking if no evaluation metric is provided.");
}
if (template == null) {
if (templates == null || templates.size() < 1) {
for (RatedRequest request : ratedRequests) {
if (request.getTestRequest() == null) {
throw new IllegalStateException(
@ -72,7 +73,11 @@ public class RankEvalSpec extends ToXContentToBytes implements Writeable {
}
this.ratedRequests = ratedRequests;
this.metric = metric;
this.template = template;
if (templates != null) {
for (ScriptWithId idScript : templates) {
this.templates.put(idScript.id, idScript.script);
}
}
}
public RankEvalSpec(Collection<RatedRequest> ratedRequests, RankedListQualityMetric metric) {
@ -80,29 +85,31 @@ public class RankEvalSpec extends ToXContentToBytes implements Writeable {
}
public RankEvalSpec(StreamInput in) throws IOException {
int specSize = in.readInt();
int specSize = in.readVInt();
ratedRequests = new ArrayList<>(specSize);
for (int i = 0; i < specSize; i++) {
ratedRequests.add(new RatedRequest(in));
}
metric = in.readNamedWriteable(RankedListQualityMetric.class);
if (in.readBoolean()) {
template = new Script(in);
int size = in.readVInt();
for (int i = 0; i < size; i++) {
String key = in.readString();
Script value = new Script(in);
this.templates.put(key, value);
}
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeInt(ratedRequests.size());
out.writeVInt(ratedRequests.size());
for (RatedRequest spec : ratedRequests) {
spec.writeTo(out);
}
out.writeNamedWriteable(metric);
if (template != null) {
out.writeBoolean(true);
template.writeTo(out);
} else {
out.writeBoolean(false);
out.writeVInt(templates.size());
for (Entry<String, Script> entry : templates.entrySet()) {
out.writeString(entry.getKey());
entry.getValue().writeTo(out);
}
}
@ -117,17 +124,17 @@ public class RankEvalSpec extends ToXContentToBytes implements Writeable {
}
/** Returns the template to base test requests on. */
public Script getTemplate() {
return this.template;
public Map<String, Script> getTemplates() {
return this.templates;
}
private static final ParseField TEMPLATE_FIELD = new ParseField("template");
private static final ParseField TEMPLATES_FIELD = new ParseField("templates");
private static final ParseField METRIC_FIELD = new ParseField("metric");
private static final ParseField REQUESTS_FIELD = new ParseField("requests");
@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<RankEvalSpec, RankEvalContext> PARSER =
new ConstructingObjectParser<>("rank_eval",
a -> new RankEvalSpec((Collection<RatedRequest>) a[0], (RankedListQualityMetric) a[1], (Script) a[2]));
a -> new RankEvalSpec((Collection<RatedRequest>) a[0], (RankedListQualityMetric) a[1], (Collection<ScriptWithId>) a[2]));
static {
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), (p, c) -> {
@ -144,7 +151,41 @@ public class RankEvalSpec extends ToXContentToBytes implements Writeable {
throw new ParsingException(p.getTokenLocation(), "error parsing rank request", ex);
}
} , METRIC_FIELD);
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), (p, c) -> {
PARSER.declareObjectArray(ConstructingObjectParser.optionalConstructorArg(), (p, c) -> {
try {
return ScriptWithId.fromXContent(p, c);
} catch (IOException ex) {
throw new ParsingException(p.getTokenLocation(), "error parsing rank request", ex);
}
}, TEMPLATES_FIELD);
}
public static RankEvalSpec parse(XContentParser parser, RankEvalContext context) throws IOException {
return PARSER.apply(parser, context);
}
public static class ScriptWithId {
private Script script;
private String id;
private static final ParseField TEMPLATE_FIELD = new ParseField("template");
private static final ParseField TEMPLATE_ID_FIELD = new ParseField("id");
public ScriptWithId(String id, Script script) {
this.id = id;
this.script = script;
}
private static final ConstructingObjectParser<ScriptWithId, RankEvalContext> PARSER =
new ConstructingObjectParser<>("script_with_id", a -> new ScriptWithId((String) a[0], (Script) a[1]));
public static ScriptWithId fromXContent(XContentParser parser, RankEvalContext context) throws IOException {
return PARSER.apply(parser, context);
}
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), TEMPLATE_ID_FIELD);
PARSER.declareObject(ConstructingObjectParser.constructorArg(), (p, c) -> {
try {
return Script.parse(p, c.getParseFieldMatcher(), "mustache");
} catch (IOException ex) {
@ -152,17 +193,20 @@ public class RankEvalSpec extends ToXContentToBytes implements Writeable {
}
}, TEMPLATE_FIELD);
}
public static RankEvalSpec parse(XContentParser parser, RankEvalContext context) throws IOException {
return PARSER.apply(parser, context);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
if (this.template != null) {
builder.field(TEMPLATE_FIELD.getPreferredName(), this.template);
builder.startArray(TEMPLATES_FIELD.getPreferredName());
for (Entry<String, Script> entry : templates.entrySet()) {
builder.startObject();
builder.field(ScriptWithId.TEMPLATE_ID_FIELD.getPreferredName(), entry.getKey());
builder.field(ScriptWithId.TEMPLATE_FIELD.getPreferredName(), entry.getValue());
builder.endObject();
}
builder.endArray();
builder.startArray(REQUESTS_FIELD.getPreferredName());
for (RatedRequest spec : this.ratedRequests) {
spec.toXContent(builder, params);
@ -185,11 +229,11 @@ public class RankEvalSpec extends ToXContentToBytes implements Writeable {
return Objects.equals(ratedRequests, other.ratedRequests) &&
Objects.equals(metric, other.metric) &&
Objects.equals(template, other.template);
Objects.equals(templates, other.templates);
}
@Override
public final int hashCode() {
return Objects.hash(ratedRequests, metric, template);
return Objects.hash(ratedRequests, metric, templates);
}
}

View File

@ -60,16 +60,27 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
private SearchSourceBuilder testRequest;
/** Map of parameters to use for filling a query template, can be used instead of providing testRequest. */
private Map<String, Object> params = new HashMap<>();
@Nullable
private String templateId;
public RatedRequest(String id, List<RatedDocument> ratedDocs, SearchSourceBuilder testRequest, Map<String, Object> params) {
public RatedRequest(
String id, List<RatedDocument> ratedDocs, SearchSourceBuilder testRequest, Map<String, Object> params, String templateId) {
if (params != null && (params.size() > 0 && testRequest != null)) {
throw new IllegalArgumentException(
"Ambiguous rated request: Set both, verbatim test request and test request template parameters.");
}
if (templateId != null && testRequest != null) {
throw new IllegalArgumentException(
"Ambiguous rated request: Set both, verbatim test request and test request template parameters.");
}
if ((params == null || params.size() < 1) && testRequest == null) {
throw new IllegalArgumentException(
"Need to set at least test request or test request template parameters.");
}
if ((params != null && params.size() > 0) && templateId == null) {
throw new IllegalArgumentException(
"If template parameters are supplied need to set id of template to apply them to too.");
}
// No documents with same _index/_type/id allowed.
Set<DocumentKey> docKeys = new HashSet<>();
for (RatedDocument doc : ratedDocs) {
@ -86,14 +97,15 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
if (params != null) {
this.params = params;
}
this.templateId = templateId;
}
public RatedRequest(String id, List<RatedDocument> ratedDocs, Map<String, Object> params) {
this(id, ratedDocs, null, params);
public RatedRequest(String id, List<RatedDocument> ratedDocs, Map<String, Object> params, String templateId) {
this(id, ratedDocs, null, params, templateId);
}
public RatedRequest(String id, List<RatedDocument> ratedDocs, SearchSourceBuilder testRequest) {
this(id, ratedDocs, testRequest, new HashMap<>());
this(id, ratedDocs, testRequest, new HashMap<>(), null);
}
public RatedRequest(StreamInput in) throws IOException {
@ -121,6 +133,7 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
for (int i = 0; i < summaryFieldsSize; i++) {
this.summaryFields.add(in.readString());
}
this.templateId = in.readOptionalString();
}
@Override
@ -145,6 +158,7 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
for (String fieldName : summaryFields) {
out.writeString(fieldName);
}
out.writeOptionalString(this.templateId);
}
public SearchSourceBuilder getTestRequest() {
@ -181,6 +195,10 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
return this.params;
}
public String getTemplateId() {
return this.templateId;
}
/** Returns a list of fields that are included in the docs summary of matched documents. */
public List<String> getSummaryFields() {
return summaryFields;
@ -198,10 +216,11 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
private static final ParseField RATINGS_FIELD = new ParseField("ratings");
private static final ParseField PARAMS_FIELD = new ParseField("params");
private static final ParseField FIELDS_FIELD = new ParseField("summary_fields");
private static final ParseField TEMPLATE_ID_FIELD = new ParseField("template_id");
private static final ConstructingObjectParser<RatedRequest, RankEvalContext> PARSER =
new ConstructingObjectParser<>("requests", a -> new RatedRequest(
(String) a[0], (List<RatedDocument>) a[1], (SearchSourceBuilder) a[2], (Map<String, Object>) a[3]));
(String) a[0], (List<RatedDocument>) a[1], (SearchSourceBuilder) a[2], (Map<String, Object>) a[3], (String) a[4]));
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), ID_FIELD);
@ -227,6 +246,7 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
}
}, PARAMS_FIELD);
PARSER.declareStringArray(RatedRequest::setSummaryFields, FIELDS_FIELD);
PARSER.declareString(ConstructingObjectParser.optionalConstructorArg(), TEMPLATE_ID_FIELD);
}
/**
@ -278,6 +298,9 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
}
builder.endArray();
}
if (this.templateId != null) {
builder.field(TEMPLATE_ID_FIELD.getPreferredName(), this.templateId);
}
builder.endObject();
return builder;
}
@ -299,11 +322,12 @@ public class RatedRequest extends ToXContentToBytes implements Writeable {
Objects.equals(types, other.types) &&
Objects.equals(summaryFields, other.summaryFields) &&
Objects.equals(ratedDocs, other.ratedDocs) &&
Objects.equals(params, other.params);
Objects.equals(params, other.params) &&
Objects.equals(templateId, other.templateId);
}
@Override
public final int hashCode() {
return Objects.hash(id, testRequest, indices, types, summaryFields, ratedDocs, params);
return Objects.hash(id, testRequest, indices, types, summaryFields, ratedDocs, params, templateId);
}
}

View File

@ -21,16 +21,13 @@ package org.elasticsearch.index.rankeval;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
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.index.query.QueryParseContext;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestActions;
import org.elasticsearch.rest.action.RestToXContentListener;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchRequestParsers;

View File

@ -33,6 +33,7 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.script.CompiledScript;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptContext;
import org.elasticsearch.script.ScriptService;
import org.elasticsearch.search.SearchHit;
@ -46,6 +47,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
@ -84,9 +86,11 @@ public class TransportRankEvalAction extends HandledTransportAction<RankEvalRequ
Map<String, EvalQueryQuality> partialResults = new ConcurrentHashMap<>(specifications.size());
Map<String, Exception> errors = new ConcurrentHashMap<>(specifications.size());
CompiledScript scriptWithoutParams = null;
if (qualityTask.getTemplate() != null) {
scriptWithoutParams = scriptService.compile(qualityTask.getTemplate(), ScriptContext.Standard.SEARCH, new HashMap<>());
Map<String, CompiledScript> scriptsWithoutParams = new HashMap<>();
for (Entry<String, Script> entry : qualityTask.getTemplates().entrySet()) {
scriptsWithoutParams.put(
entry.getKey(),
scriptService.compile(entry.getValue(), ScriptContext.Standard.SEARCH, new HashMap<>()));
}
for (RatedRequest ratedRequest : specifications) {
final RankEvalActionListener searchListener = new RankEvalActionListener(listener, qualityTask.getMetric(), ratedRequest,
@ -94,7 +98,9 @@ public class TransportRankEvalAction extends HandledTransportAction<RankEvalRequ
SearchSourceBuilder ratedSearchSource = ratedRequest.getTestRequest();
if (ratedSearchSource == null) {
Map<String, Object> params = ratedRequest.getParams();
String resolvedRequest = ((BytesReference) (scriptService.executable(scriptWithoutParams, params).run())).utf8ToString();
String templateId = ratedRequest.getTemplateId();
CompiledScript compiled = scriptsWithoutParams.get(templateId);
String resolvedRequest = ((BytesReference) (scriptService.executable(compiled, params).run())).utf8ToString();
try (XContentParser subParser = XContentFactory.xContent(resolvedRequest).createParser(resolvedRequest)) {
QueryParseContext parseContext = new QueryParseContext(searchRequestParsers.queryParsers, subParser, parseFieldMatcher);
ratedSearchSource = SearchSourceBuilder.fromXContent(parseContext, searchRequestParsers.aggParsers,

View File

@ -28,6 +28,7 @@ import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.query.QueryParseContext;
import org.elasticsearch.index.rankeval.RankEvalSpec.ScriptWithId;
import org.elasticsearch.indices.query.IndicesQueriesRegistry;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
@ -43,8 +44,10 @@ import org.junit.BeforeClass;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
@ -91,8 +94,9 @@ public class RankEvalSpecTests extends ESTestCase {
metric = DiscountedCumulativeGainTests.createTestItem();
}
Script template = null;
List<RatedRequest> ratedRequests = null;
Collection<ScriptWithId> templates = null;
if (randomBoolean()) {
final Map<String, Object> params = randomBoolean() ? Collections.emptyMap() : Collections.singletonMap("key", "value");
ScriptType scriptType = randomFrom(ScriptType.values());
@ -108,20 +112,21 @@ public class RankEvalSpecTests extends ESTestCase {
script = randomAsciiOfLengthBetween(1, 5);
}
template = new Script(scriptType, randomFrom("_lang1", "_lang2"), script, params);
templates = new HashSet<>();
templates.add(
new ScriptWithId("templateId", new Script(scriptType, randomFrom("_lang1", "_lang2"), script, params)));
Map<String, Object> templateParams = new HashMap<>();
templateParams.put("key", "value");
RatedRequest ratedRequest = new RatedRequest(
"id", Arrays.asList(RatedDocumentTests.createRatedDocument()), templateParams);
"id", Arrays.asList(RatedDocumentTests.createRatedDocument()), templateParams, "templateId");
ratedRequests = Arrays.asList(ratedRequest);
} else {
RatedRequest ratedRequest = new RatedRequest(
"id", Arrays.asList(RatedDocumentTests.createRatedDocument()), new SearchSourceBuilder());
ratedRequests = Arrays.asList(ratedRequest);
}
return new RankEvalSpec(ratedRequests, metric, template);
return new RankEvalSpec(ratedRequests, metric, templates);
}
public void testRoundtripping() throws IOException {
@ -159,7 +164,7 @@ public class RankEvalSpecTests extends ESTestCase {
Map<String, Object> params = new HashMap<>();
params.put("key", "value");
RatedRequest request = new RatedRequest("id", ratedDocs, params);
RatedRequest request = new RatedRequest("id", ratedDocs, params, "templateId");
List<RatedRequest> ratedRequests = Arrays.asList(request);
expectThrows(IllegalStateException.class, () -> new RankEvalSpec(ratedRequests, new Precision()));

View File

@ -107,7 +107,7 @@ public class RatedRequestsTests extends ESTestCase {
ratedRequest.setTypes(types);
ratedRequest.setSummaryFields(summaryFields);
} else {
ratedRequest = new RatedRequest(requestId, ratedDocs, params);
ratedRequest = new RatedRequest(requestId, ratedDocs, params, randomAsciiOfLength(5));
ratedRequest.setIndices(indices);
ratedRequest.setTypes(types);
ratedRequest.setSummaryFields(summaryFields);
@ -200,8 +200,9 @@ public class RatedRequestsTests extends ESTestCase {
List<String> types = original.getTypes();
Map<String, Object> params = original.getParams();
List<String> summaryFields = original.getSummaryFields();
String templateId = original.getTemplateId();
int mutate = randomIntBetween(0, 6);
int mutate = randomIntBetween(0, 7);
switch (mutate) {
case 0:
id = randomValueOtherThan(id, () -> randomAsciiOfLength(10));
@ -230,11 +231,14 @@ public class RatedRequestsTests extends ESTestCase {
case 6:
summaryFields = Arrays.asList(randomValueOtherThanMany(summaryFields::contains, () -> randomAsciiOfLength(10)));
break;
case 7:
templateId = randomValueOtherThan(templateId, () -> randomAsciiOfLength(5));
break;
default:
throw new IllegalStateException("Requested to modify more than available parameters.");
}
RatedRequest ratedRequest = new RatedRequest(id, ratedDocs, testRequest, params);
RatedRequest ratedRequest = new RatedRequest(id, ratedDocs, testRequest, params, templateId);
ratedRequest.setIndices(indices);
ratedRequest.setTypes(types);
ratedRequest.setSummaryFields(summaryFields);
@ -258,7 +262,7 @@ public class RatedRequestsTests extends ESTestCase {
params.put("key", "value");
ex = expectThrows(
IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, params));
() -> new RatedRequest("id", ratedDocs, params, "templateId"));
assertEquals(
"Found duplicate rated document key [{ \"_index\" : \"index1\", \"_type\" : \"type1\", \"_id\" : \"id1\"}]",
ex.getMessage());
@ -272,7 +276,7 @@ public class RatedRequestsTests extends ESTestCase {
public void testNullParamsTreatment() {
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
RatedRequest request = new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), null);
RatedRequest request = new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), null, null);
assertNotNull(request.getParams());
}
@ -281,13 +285,33 @@ public class RatedRequestsTests extends ESTestCase {
Map<String, Object> params = new HashMap<>();
params.put("key", "value");
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), params));
() -> new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), params, null));
}
public void testSettingNeitherParamsNorRequestThrows() {
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, null, null));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, null, new HashMap<>()));
expectThrows(IllegalArgumentException.class, () -> new RatedRequest("id", ratedDocs, null, new HashMap<>(), "templateId"));
}
public void testSettingParamsWithoutTemplateIdThrows() {
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
Map<String, Object> params = new HashMap<>();
params.put("key", "value");
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, null, params, null));
}
public void testSettingTemplateIdAndRequestThrows() {
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, new SearchSourceBuilder(), null, "templateId"));
}
public void testSettingTemplateIdNoParamsThrows() {
List<RatedDocument> ratedDocs = Arrays.asList(new RatedDocument(new DocumentKey("index1", "type1", "id1"), 1));
expectThrows(IllegalArgumentException.class,
() -> new RatedRequest("id", ratedDocs, null, null, "templateId"));
}
public void testParseFromXContent() throws IOException {

View File

@ -28,6 +28,7 @@ import org.elasticsearch.index.rankeval.RankEvalResponse;
import org.elasticsearch.index.rankeval.RankEvalSpec;
import org.elasticsearch.index.rankeval.RatedDocument;
import org.elasticsearch.index.rankeval.RatedRequest;
import org.elasticsearch.index.rankeval.RankEvalSpec.ScriptWithId;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
@ -39,12 +40,16 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SmokeMultipleTemplatesIT extends ESIntegTestCase {
private static final String MATCH_TEMPLATE = "match_template";
@Override
protected Collection<Class<? extends Plugin>> transportClientPlugins() {
return Arrays.asList(RankEvalPlugin.class);
@ -82,7 +87,8 @@ public class SmokeMultipleTemplatesIT extends ESIntegTestCase {
List<RatedRequest> specifications = new ArrayList<>();
Map<String, Object> ams_params = new HashMap<>();
ams_params.put("querystring", "amsterdam");
RatedRequest amsterdamRequest = new RatedRequest("amsterdam_query", createRelevant("2", "3", "4", "5"), ams_params);
RatedRequest amsterdamRequest = new RatedRequest(
"amsterdam_query", createRelevant("2", "3", "4", "5"), ams_params, MATCH_TEMPLATE);
amsterdamRequest.setIndices(indices);
amsterdamRequest.setTypes(types);
@ -90,19 +96,24 @@ public class SmokeMultipleTemplatesIT extends ESIntegTestCase {
Map<String, Object> berlin_params = new HashMap<>();
berlin_params.put("querystring", "berlin");
RatedRequest berlinRequest = new RatedRequest("berlin_query", createRelevant("1"), berlin_params);
RatedRequest berlinRequest = new RatedRequest(
"berlin_query", createRelevant("1"), berlin_params, MATCH_TEMPLATE);
berlinRequest.setIndices(indices);
berlinRequest.setTypes(types);
specifications.add(berlinRequest);
Precision metric = new Precision();
Script template =
ScriptWithId template =
new ScriptWithId(
MATCH_TEMPLATE,
new Script(
ScriptType.INLINE,
"mustache", "{\"query\": {\"match\": {\"text\": \"{{querystring}}\"}}}",
new HashMap<>());
RankEvalSpec task = new RankEvalSpec(specifications, metric, template);
new HashMap<>()));
Set<ScriptWithId> templates = new HashSet<>();
templates.add(template);
RankEvalSpec task = new RankEvalSpec(specifications, metric, templates);
RankEvalRequestBuilder builder = new RankEvalRequestBuilder(client(), RankEvalAction.INSTANCE, new RankEvalRequest());
builder.setRankEvalSpec(task);

View File

@ -41,13 +41,12 @@
- do:
rank_eval:
body: {
"template": {
"inline": "{\"query\": { \"match\" : {\"text\" : \"{{query_string}}\" }}}"
},
"templates": [ { "id": "match", "template": {"inline": "{\"query\": { \"match\" : {\"text\" : \"{{query_string}}\" }}}" }} ],
"requests" : [
{
"id": "amsterdam_query",
"params": { "query_string": "amsterdam" },
"template_id": "match",
"ratings": [
{"_index": "foo", "_type": "bar", "_id": "doc1", "rating": 0},
{"_index": "foo", "_type": "bar", "_id": "doc2", "rating": 1},
@ -56,6 +55,7 @@
{
"id" : "berlin_query",
"params": { "query_string": "berlin" },
"template_id": "match",
"ratings": [{"_index": "foo", "_type": "bar", "_id": "doc1", "rating": 1}]
}
],