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
|
// 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("*")) {
|
if (context.fieldNames().get(0).equals("*")) {
|
||||||
return null;
|
return AllButSourceFieldSelector.INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldMappersFieldSelector fieldSelector = new FieldMappersFieldSelector();
|
FieldMappersFieldSelector fieldSelector = new FieldMappersFieldSelector();
|
||||||
|
|
|
@ -36,20 +36,26 @@ public class FieldsParseElement implements SearchParseElement {
|
||||||
if (token == XContentParser.Token.START_ARRAY) {
|
if (token == XContentParser.Token.START_ARRAY) {
|
||||||
boolean added = false;
|
boolean added = false;
|
||||||
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
|
||||||
added = true;
|
|
||||||
String name = parser.text();
|
String name = parser.text();
|
||||||
if (name.contains("_source.") || name.contains("doc[")) {
|
if (name.contains("_source.") || name.contains("doc[")) {
|
||||||
// script field to load from source
|
// script field to load from source
|
||||||
SearchScript searchScript = new SearchScript(context.lookup(), null, name, null, context.scriptService());
|
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 {
|
} else {
|
||||||
FieldMapper fieldMapper = context.mapperService().smartNameFieldMapper(name);
|
if ("*".equals(name)) {
|
||||||
if (!"*".equals(name) && (fieldMapper == null || !fieldMapper.stored())) {
|
added = true;
|
||||||
// script field to load from source
|
context.fieldNames().add("*");
|
||||||
SearchScript searchScript = new SearchScript(context.lookup(), null, "_source." + name, null, context.scriptService());
|
|
||||||
context.scriptFields().add(new ScriptFieldsContext.ScriptField(name, searchScript));
|
|
||||||
} else {
|
} else {
|
||||||
context.fieldNames().add(name);
|
FieldMapper fieldMapper = context.mapperService().smartNameFieldMapper(name);
|
||||||
|
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[")) {
|
if (name.contains("_source.") || name.contains("doc[")) {
|
||||||
// script field to load from source
|
// script field to load from source
|
||||||
SearchScript searchScript = new SearchScript(context.lookup(), null, name, null, context.scriptService());
|
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 {
|
} else {
|
||||||
FieldMapper fieldMapper = context.mapperService().smartNameFieldMapper(name);
|
if ("*".equals(name)) {
|
||||||
if (!"*".equals(name) && (fieldMapper == null || !fieldMapper.stored())) {
|
context.fieldNames().add("*");
|
||||||
// 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 {
|
} else {
|
||||||
context.fieldNames().add(name);
|
FieldMapper fieldMapper = context.mapperService().smartNameFieldMapper(name);
|
||||||
|
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 {
|
public static class ScriptField {
|
||||||
private final String name;
|
private final String name;
|
||||||
private final SearchScript script;
|
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.name = name;
|
||||||
this.script = script;
|
this.script = script;
|
||||||
|
this.ignoreException = ignoreException;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String name() {
|
public String name() {
|
||||||
|
@ -45,6 +47,10 @@ public class ScriptFieldsContext {
|
||||||
public SearchScript script() {
|
public SearchScript script() {
|
||||||
return this.script;
|
return this.script;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean ignoreException() {
|
||||||
|
return ignoreException;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<ScriptField> fields = Lists.newArrayList();
|
private List<ScriptField> fields = Lists.newArrayList();
|
||||||
|
|
|
@ -53,6 +53,7 @@ public class ScriptFieldsParseElement implements SearchParseElement {
|
||||||
String script = null;
|
String script = null;
|
||||||
String scriptLang = null;
|
String scriptLang = null;
|
||||||
Map<String, Object> params = null;
|
Map<String, Object> params = null;
|
||||||
|
boolean ignoreException = false;
|
||||||
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();
|
||||||
|
@ -63,11 +64,13 @@ public class ScriptFieldsParseElement implements SearchParseElement {
|
||||||
script = parser.text();
|
script = parser.text();
|
||||||
} else if ("lang".equals(currentFieldName)) {
|
} else if ("lang".equals(currentFieldName)) {
|
||||||
scriptLang = parser.text();
|
scriptLang = parser.text();
|
||||||
|
} else if ("ignore_failure".equals(currentFieldName)) {
|
||||||
|
ignoreException = parser.booleanValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SearchScript searchScript = new SearchScript(context.lookup(), scriptLang, script, params, context.scriptService());
|
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()) {
|
for (ScriptFieldsContext.ScriptField scriptField : context.scriptFields().fields()) {
|
||||||
scriptField.script().setNextReader(reader);
|
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) {
|
if (hit.fieldsOrNull() == null) {
|
||||||
hit.fields(new HashMap<String, SearchHitField>(2));
|
hit.fields(new HashMap<String, SearchHitField>(2));
|
||||||
|
|
Loading…
Reference in New Issue