earch API: Automatically identify "script" fields on the field elements in search, close #357.
This commit is contained in:
parent
243b7455e8
commit
f270fc00d2
|
@ -135,7 +135,7 @@ public class FetchPhase implements SearchPhase {
|
|||
hitField.values().add(value);
|
||||
}
|
||||
|
||||
if (context.scriptFields() != null) {
|
||||
if (context.hasScriptFields()) {
|
||||
sameDocCache.clear();
|
||||
int readerIndex = context.searcher().readerIndex(docId);
|
||||
IndexReader subReader = context.searcher().subReaders()[readerIndex];
|
||||
|
@ -203,12 +203,12 @@ public class FetchPhase implements SearchPhase {
|
|||
}
|
||||
|
||||
private FieldSelector buildFieldSelectors(SearchContext context) {
|
||||
if (context.scriptFields() != null && context.fieldNames() == null) {
|
||||
if (context.hasScriptFields() && !context.hasFieldNames()) {
|
||||
// we ask for script fields, and no field names, don't load the source
|
||||
return UidFieldSelector.INSTANCE;
|
||||
}
|
||||
|
||||
if (context.fieldNames() == null) {
|
||||
if (!context.hasFieldNames()) {
|
||||
return new UidAndSourceFieldSelector();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,13 +19,12 @@
|
|||
|
||||
package org.elasticsearch.search.fetch;
|
||||
|
||||
import org.elasticsearch.common.collect.ImmutableList;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.field.function.script.ScriptFieldsFunction;
|
||||
import org.elasticsearch.search.SearchParseElement;
|
||||
import org.elasticsearch.search.fetch.script.ScriptFieldsContext;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author kimchy (shay.banon)
|
||||
*/
|
||||
|
@ -34,17 +33,28 @@ public class FieldsParseElement implements SearchParseElement {
|
|||
@Override public void parse(XContentParser parser, SearchContext context) throws Exception {
|
||||
XContentParser.Token token = parser.currentToken();
|
||||
if (token == XContentParser.Token.START_ARRAY) {
|
||||
ArrayList<String> fieldNames = new ArrayList<String>();
|
||||
boolean added = false;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
fieldNames.add(parser.text());
|
||||
added = true;
|
||||
String name = parser.text();
|
||||
if (name.contains("_source.") || name.contains("doc[")) {
|
||||
// script field to load from source
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, new ScriptFieldsFunction(name, context.scriptService(), context.mapperService(), context.fieldDataCache()), null));
|
||||
} else {
|
||||
context.fieldNames().add(name);
|
||||
}
|
||||
}
|
||||
if (fieldNames.isEmpty()) {
|
||||
context.fieldNames(ImmutableList.<String>of());
|
||||
} else {
|
||||
context.fieldNames(fieldNames);
|
||||
if (!added) {
|
||||
context.emptyFieldNames();
|
||||
}
|
||||
} else if (token == XContentParser.Token.VALUE_STRING) {
|
||||
context.fieldNames(ImmutableList.of(parser.text()));
|
||||
String name = parser.text();
|
||||
if (name.contains("_source.") || name.contains("doc[")) {
|
||||
// script field to load from source
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, new ScriptFieldsFunction(name, context.scriptService(), context.mapperService(), context.fieldDataCache()), null));
|
||||
} else {
|
||||
context.fieldNames().add(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.search.fetch.script;
|
||||
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.index.field.function.script.ScriptFieldsFunction;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -53,10 +54,13 @@ public class ScriptFieldsContext {
|
|||
}
|
||||
}
|
||||
|
||||
private List<ScriptField> fields;
|
||||
private List<ScriptField> fields = Lists.newArrayList();
|
||||
|
||||
public ScriptFieldsContext(List<ScriptField> fields) {
|
||||
this.fields = fields;
|
||||
public ScriptFieldsContext() {
|
||||
}
|
||||
|
||||
public void add(ScriptField field) {
|
||||
this.fields.add(field);
|
||||
}
|
||||
|
||||
public List<ScriptField> fields() {
|
||||
|
|
|
@ -19,14 +19,11 @@
|
|||
|
||||
package org.elasticsearch.search.fetch.script;
|
||||
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.field.function.script.ScriptFieldsFunction;
|
||||
import org.elasticsearch.search.SearchParseElement;
|
||||
import org.elasticsearch.search.internal.SearchContext;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -48,7 +45,6 @@ public class ScriptFieldsParseElement implements SearchParseElement {
|
|||
@Override public void parse(XContentParser parser, SearchContext context) throws Exception {
|
||||
XContentParser.Token token;
|
||||
String currentFieldName = null;
|
||||
List<ScriptFieldsContext.ScriptField> scriptFields = Lists.newArrayList();
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
|
@ -65,11 +61,8 @@ public class ScriptFieldsParseElement implements SearchParseElement {
|
|||
script = parser.text();
|
||||
}
|
||||
}
|
||||
scriptFields.add(new ScriptFieldsContext.ScriptField(fieldName,
|
||||
new ScriptFieldsFunction(script, context.scriptService(), context.mapperService(), context.fieldDataCache()),
|
||||
params == null ? new HashMap<String, Object>() : params));
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(fieldName, new ScriptFieldsFunction(script, context.scriptService(), context.mapperService(), context.fieldDataCache()), params));
|
||||
}
|
||||
}
|
||||
context.scriptFields(new ScriptFieldsContext(scriptFields));
|
||||
}
|
||||
}
|
|
@ -22,6 +22,8 @@ package org.elasticsearch.search.internal;
|
|||
import org.apache.lucene.search.Query;
|
||||
import org.apache.lucene.search.Sort;
|
||||
import org.elasticsearch.ElasticSearchException;
|
||||
import org.elasticsearch.common.collect.ImmutableList;
|
||||
import org.elasticsearch.common.collect.Lists;
|
||||
import org.elasticsearch.common.lease.Releasable;
|
||||
import org.elasticsearch.common.timer.Timeout;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
|
@ -198,12 +200,15 @@ public class SearchContext implements Releasable {
|
|||
this.highlight = highlight;
|
||||
}
|
||||
|
||||
public ScriptFieldsContext scriptFields() {
|
||||
return this.scriptFields;
|
||||
public boolean hasScriptFields() {
|
||||
return scriptFields != null;
|
||||
}
|
||||
|
||||
public void scriptFields(ScriptFieldsContext scriptFields) {
|
||||
this.scriptFields = scriptFields;
|
||||
public ScriptFieldsContext scriptFields() {
|
||||
if (scriptFields == null) {
|
||||
scriptFields = new ScriptFieldsContext();
|
||||
}
|
||||
return this.scriptFields;
|
||||
}
|
||||
|
||||
public ContextIndexSearcher searcher() {
|
||||
|
@ -322,13 +327,19 @@ public class SearchContext implements Releasable {
|
|||
return this;
|
||||
}
|
||||
|
||||
public boolean hasFieldNames() {
|
||||
return fieldNames != null;
|
||||
}
|
||||
|
||||
public List<String> fieldNames() {
|
||||
if (fieldNames == null) {
|
||||
fieldNames = Lists.newArrayList();
|
||||
}
|
||||
return fieldNames;
|
||||
}
|
||||
|
||||
public SearchContext fieldNames(List<String> fieldNames) {
|
||||
this.fieldNames = fieldNames;
|
||||
return this;
|
||||
public void emptyFieldNames() {
|
||||
this.fieldNames = ImmutableList.of();
|
||||
}
|
||||
|
||||
public boolean explain() {
|
||||
|
|
|
@ -126,13 +126,18 @@ public class ScriptFieldSearchTests extends AbstractNodesTests {
|
|||
|
||||
SearchResponse response = client.prepareSearch()
|
||||
.setQuery(matchAllQuery())
|
||||
.addField("_source.obj1") // we also automatically detect _source in fields
|
||||
.addScriptField("s_obj1", "_source.obj1")
|
||||
.addScriptField("s_obj1_test", "_source.obj1.test")
|
||||
.addScriptField("s_obj2", "_source.obj2")
|
||||
.addScriptField("s_obj2_arr2", "_source.obj2.arr2")
|
||||
.execute().actionGet();
|
||||
|
||||
Map<String, Object> sObj1 = (Map<String, Object>) response.hits().getAt(0).field("s_obj1").value();
|
||||
Map<String, Object> sObj1 = (Map<String, Object>) response.hits().getAt(0).field("_source.obj1").value();
|
||||
assertThat(sObj1.get("test").toString(), equalTo("something"));
|
||||
assertThat(response.hits().getAt(0).field("s_obj1_test").value().toString(), equalTo("something"));
|
||||
|
||||
sObj1 = (Map<String, Object>) response.hits().getAt(0).field("s_obj1").value();
|
||||
assertThat(sObj1.get("test").toString(), equalTo("something"));
|
||||
assertThat(response.hits().getAt(0).field("s_obj1_test").value().toString(), equalTo("something"));
|
||||
|
||||
|
|
Loading…
Reference in New Issue