improve logic of when to load fields from source, only if they actually have mappings, otherwise, ignore them (as was the previous behavior)
This commit is contained in:
parent
3035254885
commit
a1df3c637c
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Licensed to Elastic Search and Shay Banon under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. Elastic Search licenses this
|
||||
* file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.index.mapper;
|
||||
|
||||
import org.apache.lucene.document.FieldSelector;
|
||||
import org.apache.lucene.document.FieldSelectorResult;
|
||||
|
||||
/**
|
||||
* An optimized field selector that loads just the uid and the source.
|
||||
*
|
||||
* @author kimchy (shay.banon)
|
||||
*/
|
||||
public class AllButSourceFieldSelector implements FieldSelector {
|
||||
|
||||
public static AllButSourceFieldSelector INSTANCE = new AllButSourceFieldSelector();
|
||||
|
||||
@Override public FieldSelectorResult accept(String fieldName) {
|
||||
if (SourceFieldMapper.NAME.equals(fieldName)) {
|
||||
return FieldSelectorResult.NO_LOAD;
|
||||
}
|
||||
return FieldSelectorResult.LOAD;
|
||||
}
|
||||
}
|
|
@ -189,8 +189,9 @@ public class FetchPhase implements SearchPhase {
|
|||
}
|
||||
|
||||
// asked for all stored fields, just return null so all of them will be loaded
|
||||
// don't load the source field in this case, makes little sense to get it with all stored fields
|
||||
if (context.fieldNames().get(0).equals("*")) {
|
||||
return null;
|
||||
return AllButSourceFieldSelector.INSTANCE;
|
||||
}
|
||||
|
||||
FieldMappersFieldSelector fieldSelector = new FieldMappersFieldSelector();
|
||||
|
|
|
@ -36,20 +36,26 @@ public class FieldsParseElement implements SearchParseElement {
|
|||
if (token == XContentParser.Token.START_ARRAY) {
|
||||
boolean added = false;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||
added = true;
|
||||
String name = parser.text();
|
||||
if (name.contains("_source.") || name.contains("doc[")) {
|
||||
// script field to load from source
|
||||
SearchScript searchScript = new SearchScript(context.lookup(), null, name, null, context.scriptService());
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript));
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript, true));
|
||||
} else {
|
||||
if ("*".equals(name)) {
|
||||
added = true;
|
||||
context.fieldNames().add("*");
|
||||
} else {
|
||||
FieldMapper fieldMapper = context.mapperService().smartNameFieldMapper(name);
|
||||
if (!"*".equals(name) && (fieldMapper == null || !fieldMapper.stored())) {
|
||||
// script field to load from source
|
||||
SearchScript searchScript = new SearchScript(context.lookup(), null, "_source." + name, null, context.scriptService());
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript));
|
||||
} else {
|
||||
if (fieldMapper != null) {
|
||||
if (fieldMapper.stored()) {
|
||||
added = true;
|
||||
context.fieldNames().add(name);
|
||||
} else {
|
||||
SearchScript searchScript = new SearchScript(context.lookup(), "mvel", "_source." + fieldMapper.names().fullName(), null, context.scriptService());
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,15 +67,22 @@ public class FieldsParseElement implements SearchParseElement {
|
|||
if (name.contains("_source.") || name.contains("doc[")) {
|
||||
// script field to load from source
|
||||
SearchScript searchScript = new SearchScript(context.lookup(), null, name, null, context.scriptService());
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript));
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript, true));
|
||||
} else {
|
||||
if ("*".equals(name)) {
|
||||
context.fieldNames().add("*");
|
||||
} else {
|
||||
FieldMapper fieldMapper = context.mapperService().smartNameFieldMapper(name);
|
||||
if (!"*".equals(name) && (fieldMapper == null || !fieldMapper.stored())) {
|
||||
// script field to load from source
|
||||
SearchScript searchScript = new SearchScript(context.lookup(), null, "_source." + name, null, context.scriptService());
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript));
|
||||
} else {
|
||||
if (fieldMapper != null) {
|
||||
if (fieldMapper.stored()) {
|
||||
context.fieldNames().add(name);
|
||||
} else {
|
||||
SearchScript searchScript = new SearchScript(context.lookup(), "mvel", "_source." + fieldMapper.names().fullName(), null, context.scriptService());
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript, true));
|
||||
}
|
||||
} else {
|
||||
context.emptyFieldNames(); // don't load anything if we can't find mapping
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,10 +32,12 @@ public class ScriptFieldsContext {
|
|||
public static class ScriptField {
|
||||
private final String name;
|
||||
private final SearchScript script;
|
||||
private final boolean ignoreException;
|
||||
|
||||
public ScriptField(String name, SearchScript script) {
|
||||
public ScriptField(String name, SearchScript script, boolean ignoreException) {
|
||||
this.name = name;
|
||||
this.script = script;
|
||||
this.ignoreException = ignoreException;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
|
@ -45,6 +47,10 @@ public class ScriptFieldsContext {
|
|||
public SearchScript script() {
|
||||
return this.script;
|
||||
}
|
||||
|
||||
public boolean ignoreException() {
|
||||
return ignoreException;
|
||||
}
|
||||
}
|
||||
|
||||
private List<ScriptField> fields = Lists.newArrayList();
|
||||
|
|
|
@ -53,6 +53,7 @@ public class ScriptFieldsParseElement implements SearchParseElement {
|
|||
String script = null;
|
||||
String scriptLang = null;
|
||||
Map<String, Object> params = null;
|
||||
boolean ignoreException = false;
|
||||
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
|
||||
if (token == XContentParser.Token.FIELD_NAME) {
|
||||
currentFieldName = parser.currentName();
|
||||
|
@ -63,11 +64,13 @@ public class ScriptFieldsParseElement implements SearchParseElement {
|
|||
script = parser.text();
|
||||
} else if ("lang".equals(currentFieldName)) {
|
||||
scriptLang = parser.text();
|
||||
} else if ("ignore_failure".equals(currentFieldName)) {
|
||||
ignoreException = parser.booleanValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
SearchScript searchScript = new SearchScript(context.lookup(), scriptLang, script, params, context.scriptService());
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(fieldName, searchScript));
|
||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(fieldName, searchScript, ignoreException));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,15 @@ public class ScriptFieldsSearchHitPhase implements SearchHitPhase {
|
|||
for (ScriptFieldsContext.ScriptField scriptField : context.scriptFields().fields()) {
|
||||
scriptField.script().setNextReader(reader);
|
||||
|
||||
Object value = scriptField.script().execute(docId);
|
||||
Object value;
|
||||
try {
|
||||
value = scriptField.script().execute(docId);
|
||||
} catch (RuntimeException e) {
|
||||
if (scriptField.ignoreException()) {
|
||||
continue;
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (hit.fieldsOrNull() == null) {
|
||||
hit.fields(new HashMap<String, SearchHitField>(2));
|
||||
|
|
Loading…
Reference in New Issue