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