Add profile and explain parameters to template API

We can now run templates using `explain` and/or `profile` parameters.
Which is interesting when you have defined a complicated profile but want to debug it in an easier way than running the full query again.

You can use `explain` parameter when running a template:

```js
GET /_search/template
{
  "file": "my_template",
  "params": {
    "status": [ "pending", "published" ]
  },
  "explain": true
}
```

You can use `profile` parameter when running a template:

```js
GET /_search/template
{
  "file": "my_template",
  "params": {
    "status": [ "pending", "published" ]
  },
  "profile": true
}
```
This commit is contained in:
David Pilato 2016-09-13 18:10:52 +02:00
parent bd93b3dce6
commit ed4d0881b1
7 changed files with 102 additions and 0 deletions

View File

@ -486,6 +486,42 @@ GET /_render/template/<template_name>
} }
------------------------------------------ ------------------------------------------
[float]
===== Explain
You can use `explain` parameter when running a template:
[source,js]
------------------------------------------
GET /_search/template
{
"file": "my_template",
"params": {
"status": [ "pending", "published" ]
},
"explain": true
}
------------------------------------------
[float]
===== Profiling
You can use `profile` parameter when running a template:
[source,js]
------------------------------------------
GET /_search/template
{
"file": "my_template",
"params": {
"status": [ "pending", "published" ]
},
"profile": true
}
------------------------------------------
[[multi-search-template]] [[multi-search-template]]
== Multi Search Template == Multi Search Template

View File

@ -68,6 +68,8 @@ public class RestSearchTemplateAction extends BaseRestHandler {
request.setScriptType(ScriptService.ScriptType.STORED); request.setScriptType(ScriptService.ScriptType.STORED);
request.setScript(s); request.setScript(s);
}, new ParseField("id")); }, new ParseField("id"));
PARSER.declareBoolean(SearchTemplateRequest::setExplain, new ParseField("explain"));
PARSER.declareBoolean(SearchTemplateRequest::setProfile, new ParseField("profile"));
PARSER.declareField((parser, request, value) -> { PARSER.declareField((parser, request, value) -> {
request.setScriptType(ScriptService.ScriptType.INLINE); request.setScriptType(ScriptService.ScriptType.INLINE);
if (parser.currentToken() == XContentParser.Token.START_OBJECT) { if (parser.currentToken() == XContentParser.Token.START_OBJECT) {

View File

@ -41,6 +41,8 @@ public class SearchTemplateRequest extends ActionRequest<SearchTemplateRequest>
private SearchRequest request; private SearchRequest request;
private boolean simulate = false; private boolean simulate = false;
private boolean explain = false;
private boolean profile = false;
private ScriptService.ScriptType scriptType; private ScriptService.ScriptType scriptType;
private String script; private String script;
private Map<String, Object> scriptParams; private Map<String, Object> scriptParams;
@ -69,6 +71,22 @@ public class SearchTemplateRequest extends ActionRequest<SearchTemplateRequest>
this.simulate = simulate; this.simulate = simulate;
} }
public boolean isExplain() {
return explain;
}
public void setExplain(boolean explain) {
this.explain = explain;
}
public boolean isProfile() {
return profile;
}
public void setProfile(boolean profile) {
this.profile = profile;
}
public ScriptService.ScriptType getScriptType() { public ScriptService.ScriptType getScriptType() {
return scriptType; return scriptType;
} }
@ -123,6 +141,8 @@ public class SearchTemplateRequest extends ActionRequest<SearchTemplateRequest>
super.readFrom(in); super.readFrom(in);
request = in.readOptionalStreamable(SearchRequest::new); request = in.readOptionalStreamable(SearchRequest::new);
simulate = in.readBoolean(); simulate = in.readBoolean();
explain = in.readBoolean();
profile = in.readBoolean();
scriptType = ScriptService.ScriptType.readFrom(in); scriptType = ScriptService.ScriptType.readFrom(in);
script = in.readOptionalString(); script = in.readOptionalString();
if (in.readBoolean()) { if (in.readBoolean()) {
@ -135,6 +155,8 @@ public class SearchTemplateRequest extends ActionRequest<SearchTemplateRequest>
super.writeTo(out); super.writeTo(out);
out.writeOptionalStreamable(request); out.writeOptionalStreamable(request);
out.writeBoolean(simulate); out.writeBoolean(simulate);
out.writeBoolean(explain);
out.writeBoolean(profile);
ScriptService.ScriptType.writeTo(scriptType, out); ScriptService.ScriptType.writeTo(scriptType, out);
out.writeOptionalString(script); out.writeOptionalString(script);
boolean hasParams = scriptParams != null; boolean hasParams = scriptParams != null;

View File

@ -47,6 +47,22 @@ public class SearchTemplateRequestBuilder
return this; return this;
} }
/**
* Enables explanation for each hit on how its score was computed. Disabled by default
*/
public SearchTemplateRequestBuilder setExplain(boolean explain) {
request.setExplain(explain);
return this;
}
/**
* Enables profiling of the query. Disabled by default
*/
public SearchTemplateRequestBuilder setProfile(boolean profile) {
request.setProfile(profile);
return this;
}
public SearchTemplateRequestBuilder setScriptType(ScriptService.ScriptType scriptType) { public SearchTemplateRequestBuilder setScriptType(ScriptService.ScriptType scriptType) {
request.setScriptType(scriptType); request.setScriptType(scriptType);
return this; return this;

View File

@ -84,6 +84,8 @@ public class TransportSearchTemplateAction extends HandledTransportAction<Search
SearchSourceBuilder builder = SearchSourceBuilder.searchSource(); SearchSourceBuilder builder = SearchSourceBuilder.searchSource();
builder.parseXContent(new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher), builder.parseXContent(new QueryParseContext(searchRequestParsers.queryParsers, parser, parseFieldMatcher),
searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers); searchRequestParsers.aggParsers, searchRequestParsers.suggesters, searchRequestParsers.searchExtParsers);
builder.explain(request.isExplain());
builder.profile(request.isProfile());
searchRequest.source(builder); searchRequest.source(builder);
searchAction.execute(searchRequest, new ActionListener<SearchResponse>() { searchAction.execute(searchRequest, new ActionListener<SearchResponse>() {

View File

@ -106,3 +106,19 @@
- match: { hits.total: 1 } - match: { hits.total: 1 }
- length: { hits.hits: 1 } - length: { hits.hits: 1 }
- do:
search_template:
body: { "file" : "template_1", "params": { "size": "2", "field": "otherField", "value": "foo" }, "explain" : true }
- match: { hits.total: 1 }
- length: { hits.hits: 1 }
- match: { hits.hits.0._explanation.description: "weight(otherField:foo in 0) [PerFieldSimilarity], result of:" }
- do:
search_template:
body: { "file" : "template_1", "params": { "size": "2", "field": "otherField", "value": "foo" }, "profile" : true }
- match: { hits.total: 1 }
- length: { hits.hits: 1 }
- length: { profile: 1 }

View File

@ -46,6 +46,14 @@
"type" : "enum", "type" : "enum",
"options" : ["query_then_fetch", "query_and_fetch", "dfs_query_then_fetch", "dfs_query_and_fetch"], "options" : ["query_then_fetch", "query_and_fetch", "dfs_query_then_fetch", "dfs_query_and_fetch"],
"description" : "Search operation type" "description" : "Search operation type"
},
"explain": {
"type" : "boolean",
"description" : "Specify whether to return detailed information about score computation as part of a hit"
},
"profile": {
"type" : "boolean",
"description" : "Specify whether to profile the query execution"
} }
} }
}, },