/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.script;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.lookup.IndexField;
import org.elasticsearch.search.lookup.IndexFieldTerm;
import org.elasticsearch.search.lookup.IndexLookup;
import org.elasticsearch.search.lookup.LeafIndexLookup;
import org.elasticsearch.search.lookup.TermPosition;
import org.elasticsearch.test.ESIntegTestCase;
import org.hamcrest.Matchers;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import static java.util.Collections.emptyList;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
public class IndexLookupIT extends ESIntegTestCase {
private static final String INCLUDE_ALL = "_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS|_CACHE";
private static final int ALL_FLAGS = IndexLookup.FLAG_FREQUENCIES
| IndexLookup.FLAG_OFFSETS
| IndexLookup.FLAG_PAYLOADS
| IndexLookup.FLAG_POSITIONS
| IndexLookup.FLAG_CACHE;
private static final String INCLUDE_ALL_BUT_CACHE = "_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS";
private static final int ALL_FLAGS_WITHOUT_CACHE = IndexLookup.FLAG_FREQUENCIES
| IndexLookup.FLAG_OFFSETS
| IndexLookup.FLAG_PAYLOADS
| IndexLookup.FLAG_POSITIONS;
private HashMap<String, List<Object>> expectedEndOffsetsArray;
private HashMap<String, List<Object>> expectedPayloadsArray;
private HashMap<String, List<Object>> expectedPositionsArray;
private HashMap<String, List<Object>> expectedStartOffsetsArray;
@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
return Collections.singleton(CustomScriptPlugin.class);
}
public static class CustomScriptPlugin extends MockScriptPlugin {
@Override
@SuppressWarnings("unchecked")
protected Map<String, Function<Map<String, Object>, Object>> pluginScripts() {
Map<String, Function<Map<String, Object>, Object>> scripts = new HashMap<>();
scripts.put("term = _index['int_payload_field']['c']; term.tf()", vars -> tf(vars, "int_payload_field", "c"));
scripts.put("term = _index['int_payload_field']['b']; term.tf()", vars -> tf(vars, "int_payload_field", "b"));
scripts.put("Sum the payloads of [float_payload_field][b]", vars -> payloadSum(vars, "float_payload_field", "b"));
scripts.put("Sum the payloads of [int_payload_field][b]", vars -> payloadSum(vars, "int_payload_field", "b"));
scripts.put("createPositionsArrayScriptIterateTwice[b," + INCLUDE_ALL + ",position]",
vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS, p -> p.position));
scripts.put("createPositionsArrayScriptIterateTwice[b," + INCLUDE_ALL + ",startOffset]",
vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS, p -> p.startOffset));
scripts.put("createPositionsArrayScriptIterateTwice[b," + INCLUDE_ALL + ",endOffset]",
vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS, p -> p.endOffset));
scripts.put("createPositionsArrayScriptIterateTwice[b," + INCLUDE_ALL + ",payloadAsInt(-1)]",
vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS, p -> p.payloadAsInt(-1)));
scripts.put("createPositionsArrayScriptIterateTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,position]",
vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.position));
scripts.put("createPositionsArrayScriptIterateTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,startOffset]",
vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.startOffset));
scripts.put("createPositionsArrayScriptIterateTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,endOffset]",
vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.endOffset));
scripts.put("createPositionsArrayScriptIterateTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,payloadAsInt(-1)]",
vars -> createPositionsArrayScriptIterateTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.payloadAsInt(-1)));
scripts.put("createPositionsArrayScriptGetInfoObjectTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,position]",
vars -> createPositionsArrayScriptGetInfoObjectTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.position));
scripts.put("createPositionsArrayScriptGetInfoObjectTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,startOffset]",
vars -> createPositionsArrayScriptGetInfoObjectTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.startOffset));
scripts.put("createPositionsArrayScriptGetInfoObjectTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,endOffset]",
vars -> createPositionsArrayScriptGetInfoObjectTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.endOffset));
scripts.put("createPositionsArrayScriptGetInfoObjectTwice[b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,payloadAsInt(-1)]",
vars -> createPositionsArrayScriptGetInfoObjectTwice(vars, "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.payloadAsInt(-1)));
scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS,position]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_POSITIONS, p -> p.position));
scripts.put("createPositionsArrayScript[int_payload_field,b,_OFFSETS,position]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_OFFSETS, p -> p.position));
scripts.put("createPositionsArrayScript[int_payload_field,b,_OFFSETS,startOffset]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_OFFSETS, p -> p.startOffset));
scripts.put("createPositionsArrayScript[int_payload_field,b,_OFFSETS,endOffset]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_OFFSETS, p -> p.endOffset));
scripts.put("createPositionsArrayScript[int_payload_field,b,_OFFSETS,payloadAsInt(-1)]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_OFFSETS, p -> p.payloadAsInt(-1)));
scripts.put("createPositionsArrayScript[int_payload_field,b,_PAYLOADS,position]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_PAYLOADS, p -> p.position));
scripts.put("createPositionsArrayScript[int_payload_field,b,_PAYLOADS,startOffset]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_PAYLOADS, p -> p.startOffset));
scripts.put("createPositionsArrayScript[int_payload_field,b,_PAYLOADS,endOffset]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_PAYLOADS, p -> p.endOffset));
scripts.put("createPositionsArrayScript[int_payload_field,b,_PAYLOADS,payloadAsInt(-1)]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", IndexLookup.FLAG_PAYLOADS, p -> p.payloadAsInt(-1)));
int posoffpay = IndexLookup.FLAG_POSITIONS|IndexLookup.FLAG_OFFSETS|IndexLookup.FLAG_PAYLOADS;
scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS|_OFFSETS|_PAYLOADS,position]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", posoffpay, p -> p.position));
scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS|_OFFSETS|_PAYLOADS,startOffset]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", posoffpay, p -> p.startOffset));
scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS|_OFFSETS|_PAYLOADS,endOffset]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", posoffpay, p -> p.endOffset));
scripts.put("createPositionsArrayScript[int_payload_field,b,_POSITIONS|_OFFSETS|_PAYLOADS,payloadAsInt(-1)]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", posoffpay, p -> p.payloadAsInt(-1)));
scripts.put("createPositionsArrayScript[int_payload_field,b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,position]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.position));
scripts.put("createPositionsArrayScript[int_payload_field,b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,startOffset]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.startOffset));
scripts.put("createPositionsArrayScript[int_payload_field,b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,endOffset]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.endOffset));
scripts.put("createPositionsArrayScript[int_payload_field,b,_FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS,payloadAsInt(-1)]",
vars -> createPositionsArrayScript(vars, "int_payload_field", "b", ALL_FLAGS_WITHOUT_CACHE, p -> p.payloadAsInt(-1)));
scripts.put("createPositionsArrayScript" +
"[float_payload_field,b," + INCLUDE_ALL + ",payloadAsFloat(-1)]",
vars -> createPositionsArrayScript(vars,"float_payload_field", "b", ALL_FLAGS, p -> p.payloadAsFloat(-1)));
scripts.put("createPositionsArrayScript" +
"[string_payload_field,b," + INCLUDE_ALL + ",payloadAsString()]",
vars -> createPositionsArrayScript(vars,"string_payload_field", "b", ALL_FLAGS, TermPosition::payloadAsString));
scripts.put("createPositionsArrayScript" +
"[int_payload_field,c," + INCLUDE_ALL + ",payloadAsInt(-1)]",
vars -> createPositionsArrayScript(vars,"int_payload_field", "c", ALL_FLAGS, p -> p.payloadAsInt(-1)));
// Call with different flags twice, equivalent to:
// term = _index['int_payload_field']['b']; return _index['int_payload_field'].get('b', _POSITIONS).tf();
scripts.put("Call with different flags twice", vars -> {
LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
IndexField indexField = leafIndexLookup.get("int_payload_field");
// 1st call
indexField.get("b");
try {
// 2nd call, must throws an exception
return indexField.get("b", IndexLookup.FLAG_POSITIONS).tf();
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "Call with different flags twice", CustomScriptPlugin.NAME);
}
});
// Call with same flags twice: equivalent to:
// term = _index['int_payload_field'].get('b', _POSITIONS | _FREQUENCIES);return _index['int_payload_field']['b'].tf();
scripts.put("Call with same flags twice", vars -> {
LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
IndexField indexField = leafIndexLookup.get("int_payload_field");
// 1st call
indexField.get("b", IndexLookup.FLAG_POSITIONS | IndexLookup.FLAG_FREQUENCIES);
try {
// 2nd call, must throws an exception
return indexField.get("b").tf();
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "Call with same flags twice", CustomScriptPlugin.NAME);
}
});
// get the number of all docs
scripts.put("_index.numDocs()",
vars -> ((LeafIndexLookup) vars.get("_index")).numDocs());
// get the number of docs with field float_payload_field
scripts.put("_index['float_payload_field'].docCount()",
vars -> indexFieldScript(vars, "float_payload_field", indexField -> {
try {
return indexField.docCount();
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "docCount()", CustomScriptPlugin.NAME);
}
}));
// corner case: what if the field does not exist?
scripts.put("_index['non_existent_field'].docCount()",
vars -> indexFieldScript(vars, "non_existent_field", indexField -> {
try {
return indexField.docCount();
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "docCount()", CustomScriptPlugin.NAME);
}
}));
// get the number of all tokens in all docs
scripts.put("_index['float_payload_field'].sumttf()",
vars -> indexFieldScript(vars, "float_payload_field", indexField -> {
try {
return indexField.sumttf();
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "sumttf()", CustomScriptPlugin.NAME);
}
}));
// corner case get the number of all tokens in all docs for non existent
// field
scripts.put("_index['non_existent_field'].sumttf()",
vars -> indexFieldScript(vars, "non_existent_field", indexField -> {
try {
return indexField.sumttf();
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "sumttf()", CustomScriptPlugin.NAME);
}
}));
// get the sum of doc freqs in all docs
scripts.put("_index['float_payload_field'].sumdf()",
vars -> indexFieldScript(vars, "float_payload_field", indexField -> {
try {
return indexField.sumdf();
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "sumdf()", CustomScriptPlugin.NAME);
}
}));
// get the sum of doc freqs in all docs for non existent field
scripts.put("_index['non_existent_field'].sumdf()",
vars -> indexFieldScript(vars, "non_existent_field", indexField -> {
try {
return indexField.sumdf();
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "sumdf()", CustomScriptPlugin.NAME);
}
}));
// check term frequencies for 'a'
scripts.put("term = _index['float_payload_field']['a']; if (term != null) {term.tf()}",
vars -> indexFieldTermScript(vars, "float_payload_field", "a", indexFieldTerm -> {
try {
if (indexFieldTerm != null) {
return indexFieldTerm.tf();
}
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "term.tf()", CustomScriptPlugin.NAME);
}
return null;
}));
// check doc frequencies for 'c'
scripts.put("term = _index['float_payload_field']['c']; if (term != null) {term.df()}",
vars -> indexFieldTermScript(vars, "float_payload_field", "c", indexFieldTerm -> {
try {
if (indexFieldTerm != null) {
return indexFieldTerm.df();
}
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "term.df()", CustomScriptPlugin.NAME);
}
return null;
}));
// check doc frequencies for term that does not exist
scripts.put("term = _index['float_payload_field']['non_existent_term']; if (term != null) {term.df()}",
vars -> indexFieldTermScript(vars, "float_payload_field", "non_existent_term", indexFieldTerm -> {
try {
if (indexFieldTerm != null) {
return indexFieldTerm.df();
}
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "term.df()", CustomScriptPlugin.NAME);
}
return null;
}));
// check doc frequencies for term that does not exist
scripts.put("term = _index['non_existent_field']['non_existent_term']; if (term != null) {term.tf()}",
vars -> indexFieldTermScript(vars, "non_existent_field", "non_existent_term", indexFieldTerm -> {
try {
if (indexFieldTerm != null) {
return indexFieldTerm.tf();
}
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "term.tf()", CustomScriptPlugin.NAME);
}
return null;
}));
// check total term frequencies for 'a'
scripts.put("term = _index['float_payload_field']['a']; if (term != null) {term.ttf()}",
vars -> indexFieldTermScript(vars, "float_payload_field", "a", indexFieldTerm -> {
try {
if (indexFieldTerm != null) {
return indexFieldTerm.ttf();
}
} catch (IOException e) {
throw new ScriptException(e.getMessage(), e, emptyList(), "term.ttf()", CustomScriptPlugin.NAME);
}
return null;
}));
return scripts;
}
@SuppressWarnings("unchecked")
static Object indexFieldScript(Map<String, Object> vars, String fieldName, Function<IndexField, Object> fn) {
LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
return fn.apply(leafIndexLookup.get(fieldName));
}
@SuppressWarnings("unchecked")
static Object indexFieldTermScript(Map<String, Object> vars, String fieldName, String term, Function<IndexFieldTerm, Object> fn) {
return indexFieldScript(vars, fieldName, indexField -> fn.apply(indexField.get(term)));
}
@SuppressWarnings("unchecked")
static Object tf(Map<String, Object> vars, String fieldName, String term) {
return indexFieldTermScript(vars, fieldName, term, indexFieldTerm -> {
try {
return indexFieldTerm.tf();
} catch (IOException e) {
throw new RuntimeException("Mocked script error when retrieving TF for [" + fieldName + "][" + term + "]");
}
});
}
// Sum the payloads for a given field term, equivalent to:
// term = _index['float_payload_field'].get('b', _FREQUENCIES|_OFFSETS|_PAYLOADS|_POSITIONS|_CACHE);
// payloadSum=0;
// for (pos in term) {
// payloadSum += pos.payloadAsInt(0)
// };
// return payloadSum;
@SuppressWarnings("unchecked")
static Object payloadSum(Map<String, Object> vars, String fieldName, String term) {
return indexFieldScript(vars, fieldName, indexField -> {
IndexFieldTerm indexFieldTerm = indexField.get(term, IndexLookup.FLAG_FREQUENCIES
| IndexLookup.FLAG_OFFSETS
| IndexLookup.FLAG_PAYLOADS
| IndexLookup.FLAG_POSITIONS
| IndexLookup.FLAG_CACHE);
int payloadSum = 0;
for (TermPosition position : indexFieldTerm) {
payloadSum += position.payloadAsInt(0);
}
return payloadSum;
});
}
@SuppressWarnings("unchecked")
static List<Object> createPositionsArrayScriptGetInfoObjectTwice(Map<String, Object> vars, String term, int flags,
Function<TermPosition, Object> fn) {
LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
IndexField indexField = leafIndexLookup.get("int_payload_field");
// 1st call
IndexFieldTerm indexFieldTerm = indexField.get(term, flags);
List<Object> array = new ArrayList<>();
for (TermPosition position : indexFieldTerm) {
array.add(fn.apply(position));
}
// 2nd call
indexField.get(term, flags);
array = new ArrayList<>();
for (TermPosition position : indexFieldTerm) {
array.add(fn.apply(position));
}
return array;
}
@SuppressWarnings("unchecked")
static List<Object> createPositionsArrayScriptIterateTwice(Map<String, Object> vars, String term, int flags,
Function<TermPosition, Object> fn) {
LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
IndexField indexField = leafIndexLookup.get("int_payload_field");
IndexFieldTerm indexFieldTerm = indexField.get(term, flags);
// 1st iteration
List<Object> array = new ArrayList<>();
for (TermPosition position : indexFieldTerm) {
array.add(fn.apply(position));
}
// 2nd iteration
array = new ArrayList<>();
for (TermPosition position : indexFieldTerm) {
array.add(fn.apply(position));
}
return array;
}
@SuppressWarnings("unchecked")
static List<Object> createPositionsArrayScript(Map<String, Object> vars, String field, String term, int flags,
Function<TermPosition, Object> fn) {
LeafIndexLookup leafIndexLookup = (LeafIndexLookup) vars.get("_index");
IndexField indexField = leafIndexLookup.get(field);
IndexFieldTerm indexFieldTerm = indexField.get(term, flags);
List<Object> array = new ArrayList<>();
for (TermPosition position : indexFieldTerm) {
array.add(fn.apply(position));
}
return array;
}
}
void initTestData() throws InterruptedException, ExecutionException, IOException {
HashMap<String, List<Object>> emptyArray = new HashMap<>();
List<Object> empty1 = new ArrayList<>();
empty1.add(-1);
empty1.add(-1);
emptyArray.put("1", empty1);
List<Object> empty2 = new ArrayList<>();
empty2.add(-1);
empty2.add(-1);
emptyArray.put("2", empty2);
List<Object> empty3 = new ArrayList<>();
empty3.add(-1);
empty3.add(-1);
emptyArray.put("3", empty3);
expectedPositionsArray = new HashMap<>();
List<Object> pos1 = new ArrayList<>();
pos1.add(1);
pos1.add(2);
expectedPositionsArray.put("1", pos1);
List<Object> pos2 = new ArrayList<>();
pos2.add(0);
pos2.add(1);
expectedPositionsArray.put("2", pos2);
List<Object> pos3 = new ArrayList<>();
pos3.add(0);
pos3.add(4);
expectedPositionsArray.put("3", pos3);
expectedPayloadsArray = new HashMap<>();
List<Object> pay1 = new ArrayList<>();
pay1.add(2);
pay1.add(3);
expectedPayloadsArray.put("1", pay1);
List<Object> pay2 = new ArrayList<>();
pay2.add(1);
pay2.add(2);
expectedPayloadsArray.put("2", pay2);
List<Object> pay3 = new ArrayList<>();
pay3.add(1);
pay3.add(-1);
expectedPayloadsArray.put("3", pay3);
/*
* "a|1 b|2 b|3 c|4 d " "b|1 b|2 c|3 d|4 a " "b|1 c|2 d|3 a|4 b "
*/
expectedStartOffsetsArray = new HashMap<>();
List<Object> starts1 = new ArrayList<>();
starts1.add(4);
starts1.add(8);
expectedStartOffsetsArray.put("1", starts1);
List<Object> starts2 = new ArrayList<>();
starts2.add(0);
starts2.add(4);
expectedStartOffsetsArray.put("2", starts2);
List<Object> starts3 = new ArrayList<>();
starts3.add(0);
starts3.add(16);
expectedStartOffsetsArray.put("3", starts3);
expectedEndOffsetsArray = new HashMap<>();
List<Object> ends1 = new ArrayList<>();
ends1.add(7);
ends1.add(11);
expectedEndOffsetsArray.put("1", ends1);
List<Object> ends2 = new ArrayList<>();
ends2.add(3);
ends2.add(7);
expectedEndOffsetsArray.put("2", ends2);
List<Object> ends3 = new ArrayList<>();
ends3.add(3);
ends3.add(17);
expectedEndOffsetsArray.put("3", ends3);
XContentBuilder mapping = XContentFactory.jsonBuilder()
.startObject()
.startObject("type1")
.startObject("properties")
.startObject("int_payload_field")
.field("type", "text")
.field("index_options", "offsets")
.field("analyzer", "payload_int")
.endObject()
.endObject()
.endObject()
.endObject();
assertAcked(prepareCreate("test").addMapping("type1", mapping).setSettings(
Settings.builder()
.put(indexSettings())
.put("index.analysis.analyzer.payload_int.tokenizer", "whitespace")
.putArray("index.analysis.analyzer.payload_int.filter", "delimited_int")
.put("index.analysis.filter.delimited_int.delimiter", "|")
.put("index.analysis.filter.delimited_int.encoding", "int")
.put("index.analysis.filter.delimited_int.type", "delimited_payload_filter")));
indexRandom(true, client().prepareIndex("test", "type1", "1").setSource("int_payload_field", "a|1 b|2 b|3 c|4 d "), client()
.prepareIndex("test", "type1", "2").setSource("int_payload_field", "b|1 b|2 c|3 d|4 a "),
client().prepareIndex("test", "type1", "3").setSource("int_payload_field", "b|1 c|2 d|3 a|4 b "));
ensureGreen();
}
public void testTwoScripts() throws Exception {
initTestData();
Script scriptFieldScript = createScript("term = _index['int_payload_field']['c']; term.tf()");
Script scoreScript = createScript("term = _index['int_payload_field']['b']; term.tf()");
Map<String, Object> expectedResultsField = new HashMap<>();
expectedResultsField.put("1", 1);
expectedResultsField.put("2", 1);
expectedResultsField.put("3", 1);
Map<String, Object> expectedResultsScore = new HashMap<>();
expectedResultsScore.put("1", 2f);
expectedResultsScore.put("2", 2f);
expectedResultsScore.put("3", 2f);
checkOnlyFunctionScore(scoreScript, expectedResultsScore, 3);
checkValueInEachDocWithFunctionScore(scriptFieldScript, expectedResultsField, scoreScript, expectedResultsScore, 3);
}
public void testCallWithDifferentFlagsFails() throws Exception {
initTestData();
final int numPrimaries = getNumShards("test").numPrimaries;
final String expectedError = "You must call get with all required flags! " +
"Instead of _index['int_payload_field'].get('b', _FREQUENCIES) and _index['int_payload_field'].get('b', _POSITIONS)" +
" call _index['int_payload_field'].get('b', _FREQUENCIES | _POSITIONS) once]";
// should throw an exception, we cannot call with different flags twice
// if the flags of the second call were not included in the first call.
Script script = createScript("Call with different flags twice");
try {
SearchResponse response = client().prepareSearch("test")
.setQuery(QueryBuilders.matchAllQuery())
.addScriptField("tvtest", script)
.get();
// (partial) success when at least one shard succeeds
assertThat(numPrimaries, greaterThan(response.getShardFailures().length));
assertThat(response.getFailedShards(), greaterThanOrEqualTo(1));
for (ShardSearchFailure failure : response.getShardFailures()) {
assertThat(failure.reason(), containsString(expectedError));
}
} catch (SearchPhaseExecutionException e) {
// Exception thrown when *all* shards fail
assertThat(numPrimaries, equalTo(e.shardFailures().length));
for (ShardSearchFailure failure : e.shardFailures()) {
assertThat(failure.reason(), containsString(expectedError));
}
}
// Should not throw an exception this way round
script = createScript("Call with same flags twice");
assertThat(client().prepareSearch("test")
.setQuery(QueryBuilders.matchAllQuery())
.addScriptField("tvtest", script)
.get().getHits().getTotalHits(), greaterThan(0L));
}
private void checkOnlyFunctionScore(Script scoreScript, Map<String, Object> expectedScore, int numExpectedDocs) {
SearchResponse sr = client().prepareSearch("test")
.setQuery(QueryBuilders.functionScoreQuery(ScoreFunctionBuilders.scriptFunction(scoreScript))).execute()
.actionGet();
assertHitCount(sr, numExpectedDocs);
for (SearchHit hit : sr.getHits().getHits()) {
assertThat("for doc " + hit.getId(), ((Float) expectedScore.get(hit.getId())).doubleValue(),
Matchers.closeTo(hit.getScore(), 1.e-4));
}
}
public void testDocumentationExample() throws Exception {
initTestData();
Script script = createScript("Sum the payloads of [float_payload_field][b]");
// non existing field: sum should be 0
HashMap<String, Object> zeroArray = new HashMap<>();
zeroArray.put("1", 0);
zeroArray.put("2", 0);
zeroArray.put("3", 0);
checkValueInEachDoc(script, zeroArray, 3);
script = createScript("Sum the payloads of [int_payload_field][b]");
// existing field: sums should be as here:
zeroArray.put("1", 5);
zeroArray.put("2", 3);
zeroArray.put("3", 1);
checkValueInEachDoc(script, zeroArray, 3);
}
public void testIteratorAndRecording() throws Exception {
initTestData();
// call twice with record: should work as expected
Script script = createPositionsArrayScriptIterateTwice("b", INCLUDE_ALL, "position");
checkArrayValsInEachDoc(script, expectedPositionsArray, 3);
script = createPositionsArrayScriptIterateTwice("b", INCLUDE_ALL, "startOffset");
checkArrayValsInEachDoc(script, expectedStartOffsetsArray, 3);
script = createPositionsArrayScriptIterateTwice("b", INCLUDE_ALL, "endOffset");
checkArrayValsInEachDoc(script, expectedEndOffsetsArray, 3);
script = createPositionsArrayScriptIterateTwice("b", INCLUDE_ALL, "payloadAsInt(-1)");
checkArrayValsInEachDoc(script, expectedPayloadsArray, 3);
// no record and get iterator twice: should fail
script = createPositionsArrayScriptIterateTwice("b", INCLUDE_ALL_BUT_CACHE, "position");
checkExceptions(script);
script = createPositionsArrayScriptIterateTwice("b", INCLUDE_ALL_BUT_CACHE, "startOffset");
checkExceptions(script);
script = createPositionsArrayScriptIterateTwice("b", INCLUDE_ALL_BUT_CACHE, "endOffset");
checkExceptions(script);
script = createPositionsArrayScriptIterateTwice("b", INCLUDE_ALL_BUT_CACHE, "payloadAsInt(-1)");
checkExceptions(script);
// no record and get termObject twice and iterate: should fail
script = createPositionsArrayScriptGetInfoObjectTwice("b", INCLUDE_ALL_BUT_CACHE, "position");
checkExceptions(script);
script = createPositionsArrayScriptGetInfoObjectTwice("b", INCLUDE_ALL_BUT_CACHE, "startOffset");
checkExceptions(script);
script = createPositionsArrayScriptGetInfoObjectTwice("b", INCLUDE_ALL_BUT_CACHE, "endOffset");
checkExceptions(script);
script = createPositionsArrayScriptGetInfoObjectTwice("b", INCLUDE_ALL_BUT_CACHE, "payloadAsInt(-1)");
checkExceptions(script);
}
private Script createPositionsArrayScriptGetInfoObjectTwice(String term, String flags, String what) {
return createScript("createPositionsArrayScriptGetInfoObjectTwice[" + term + "," + flags + "," + what + "]");
}
private Script createPositionsArrayScriptIterateTwice(String term, String flags, String what) {
return createScript("createPositionsArrayScriptIterateTwice[" + term + "," + flags + "," + what + "]");
}
private Script createPositionsArrayScript(String field, String term, String flags, String what) {
return createScript("createPositionsArrayScript[" + field + "," + term + "," + flags + "," + what + "]");
}
private Script createPositionsArrayScriptDefaultGet(String field, String term, String what) {
return createScript("createPositionsArrayScriptDefaultGet[" + field + "," + term + "," + what + "]");
}
private Script createScript(String script) {
return new Script(ScriptType.INLINE, CustomScriptPlugin.NAME, script, Collections.emptyMap());
}
public void testFlags() throws Exception {
initTestData();
// check default flag
Script script = createPositionsArrayScriptDefaultGet("int_payload_field", "b", "position");
// there should be no positions
/* TODO: the following tests fail with the new postings enum apis because of a bogus assert in BlockDocsEnum
checkArrayValsInEachDoc(script, emptyArray, 3);
script = createPositionsArrayScriptDefaultGet("int_payload_field", "b", "startOffset");
// there should be no offsets
checkArrayValsInEachDoc(script, emptyArray, 3);
script = createPositionsArrayScriptDefaultGet("int_payload_field", "b", "endOffset");
// there should be no offsets
checkArrayValsInEachDoc(script, emptyArray, 3);
script = createPositionsArrayScriptDefaultGet("int_payload_field", "b", "payloadAsInt(-1)");
// there should be no payload
checkArrayValsInEachDoc(script, emptyArray, 3);
// check FLAG_FREQUENCIES flag
script = createPositionsArrayScript("int_payload_field", "b", "_FREQUENCIES", "position");
// there should be no positions
checkArrayValsInEachDoc(script, emptyArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_FREQUENCIES", "startOffset");
// there should be no offsets
checkArrayValsInEachDoc(script, emptyArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_FREQUENCIES", "endOffset");
// there should be no offsets
checkArrayValsInEachDoc(script, emptyArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_FREQUENCIES", "payloadAsInt(-1)");
// there should be no payloads
checkArrayValsInEachDoc(script, emptyArray, 3);*/
// check FLAG_POSITIONS flag
script = createPositionsArrayScript("int_payload_field", "b", "_POSITIONS", "position");
// there should be positions
checkArrayValsInEachDoc(script, expectedPositionsArray, 3);
/* TODO: these tests make a bogus assumption that asking for positions will return only positions
script = createPositionsArrayScript("int_payload_field", "b", "_POSITIONS", "startOffset");
// there should be no offsets
checkArrayValsInEachDoc(script, emptyArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_POSITIONS", "endOffset");
// there should be no offsets
checkArrayValsInEachDoc(script, emptyArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_POSITIONS", "payloadAsInt(-1)");
// there should be no payloads
checkArrayValsInEachDoc(script, emptyArray, 3);*/
// check FLAG_OFFSETS flag
script = createPositionsArrayScript("int_payload_field", "b", "_OFFSETS", "position");
// there should be positions and s forth ...
checkArrayValsInEachDoc(script, expectedPositionsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_OFFSETS", "startOffset");
checkArrayValsInEachDoc(script, expectedStartOffsetsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_OFFSETS", "endOffset");
checkArrayValsInEachDoc(script, expectedEndOffsetsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_OFFSETS", "payloadAsInt(-1)");
checkArrayValsInEachDoc(script, expectedPayloadsArray, 3);
// check FLAG_PAYLOADS flag
script = createPositionsArrayScript("int_payload_field", "b", "_PAYLOADS", "position");
checkArrayValsInEachDoc(script, expectedPositionsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_PAYLOADS", "startOffset");
checkArrayValsInEachDoc(script, expectedStartOffsetsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_PAYLOADS", "endOffset");
checkArrayValsInEachDoc(script, expectedEndOffsetsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", "_PAYLOADS", "payloadAsInt(-1)");
checkArrayValsInEachDoc(script, expectedPayloadsArray, 3);
// check all flags
String allFlags = "_POSITIONS|_OFFSETS|_PAYLOADS";
script = createPositionsArrayScript("int_payload_field", "b", allFlags, "position");
checkArrayValsInEachDoc(script, expectedPositionsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", allFlags, "startOffset");
checkArrayValsInEachDoc(script, expectedStartOffsetsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", allFlags, "endOffset");
checkArrayValsInEachDoc(script, expectedEndOffsetsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", allFlags, "payloadAsInt(-1)");
checkArrayValsInEachDoc(script, expectedPayloadsArray, 3);
// check all flags without record
script = createPositionsArrayScript("int_payload_field", "b", INCLUDE_ALL_BUT_CACHE, "position");
checkArrayValsInEachDoc(script, expectedPositionsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", INCLUDE_ALL_BUT_CACHE, "startOffset");
checkArrayValsInEachDoc(script, expectedStartOffsetsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", INCLUDE_ALL_BUT_CACHE, "endOffset");
checkArrayValsInEachDoc(script, expectedEndOffsetsArray, 3);
script = createPositionsArrayScript("int_payload_field", "b", INCLUDE_ALL_BUT_CACHE, "payloadAsInt(-1)");
checkArrayValsInEachDoc(script, expectedPayloadsArray, 3);
}
private void checkArrayValsInEachDoc(Script script, HashMap<String, List<Object>> expectedArray, int expectedHitSize) {
SearchResponse sr = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()).addScriptField("tvtest", script)
.execute().actionGet();
assertHitCount(sr, expectedHitSize);
int nullCounter = 0;
for (SearchHit hit : sr.getHits().getHits()) {
Object result = hit.getFields().get("tvtest").getValues();
Object expectedResult = expectedArray.get(hit.getId());
assertThat("for doc " + hit.getId(), result, equalTo(expectedResult));
if (expectedResult != null) {
nullCounter++;
}
}
assertThat(nullCounter, equalTo(expectedArray.size()));
}
public void testAllExceptPosAndOffset() throws Exception {
XContentBuilder mapping = XContentFactory.jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("float_payload_field").field("type", "text").field("index_options", "offsets").field("term_vector", "no")
.field("analyzer", "payload_float").endObject().startObject("string_payload_field").field("type", "text")
.field("index_options", "offsets").field("term_vector", "no").field("analyzer", "payload_string").endObject()
.startObject("int_payload_field").field("type", "text").field("index_options", "offsets")
.field("analyzer", "payload_int").endObject().endObject().endObject().endObject();
assertAcked(prepareCreate("test").addMapping("type1", mapping).setSettings(
Settings.builder()
.put(indexSettings())
.put("index.analysis.analyzer.payload_float.tokenizer", "whitespace")
.putArray("index.analysis.analyzer.payload_float.filter", "delimited_float")
.put("index.analysis.filter.delimited_float.delimiter", "|")
.put("index.analysis.filter.delimited_float.encoding", "float")
.put("index.analysis.filter.delimited_float.type", "delimited_payload_filter")
.put("index.analysis.analyzer.payload_string.tokenizer", "whitespace")
.putArray("index.analysis.analyzer.payload_string.filter", "delimited_string")
.put("index.analysis.filter.delimited_string.delimiter", "|")
.put("index.analysis.filter.delimited_string.encoding", "identity")
.put("index.analysis.filter.delimited_string.type", "delimited_payload_filter")
.put("index.analysis.analyzer.payload_int.tokenizer", "whitespace")
.putArray("index.analysis.analyzer.payload_int.filter", "delimited_int")
.put("index.analysis.filter.delimited_int.delimiter", "|")
.put("index.analysis.filter.delimited_int.encoding", "int")
.put("index.analysis.filter.delimited_int.type", "delimited_payload_filter")
.put("index.number_of_shards", 1)));
indexRandom(true, client().prepareIndex("test", "type1", "1").setSource("float_payload_field", "a|1 b|2 a|3 b "), client()
.prepareIndex("test", "type1", "2").setSource("string_payload_field", "a|a b|b a|a b "),
client().prepareIndex("test", "type1", "3").setSource("float_payload_field", "a|4 b|5 a|6 b "),
client().prepareIndex("test", "type1", "4").setSource("string_payload_field", "a|b b|a a|b b "),
client().prepareIndex("test", "type1", "5").setSource("float_payload_field", "c "),
client().prepareIndex("test", "type1", "6").setSource("int_payload_field", "c|1"));
// get the number of all docs
Script script = createScript("_index.numDocs()");
checkValueInEachDoc(6, script, 6);
// get the number of docs with field float_payload_field
script = createScript("_index['float_payload_field'].docCount()");
checkValueInEachDoc(3, script, 6);
// corner case: what if the field does not exist?
script = createScript("_index['non_existent_field'].docCount()");
checkValueInEachDoc(0, script, 6);
// get the number of all tokens in all docs
script = createScript("_index['float_payload_field'].sumttf()");
checkValueInEachDoc(9, script, 6);
// corner case get the number of all tokens in all docs for non existent
// field
script = createScript("_index['non_existent_field'].sumttf()");
checkValueInEachDoc(0, script, 6);
// get the sum of doc freqs in all docs
script = createScript("_index['float_payload_field'].sumdf()");
checkValueInEachDoc(5, script, 6);
// get the sum of doc freqs in all docs for non existent field
script = createScript("_index['non_existent_field'].sumdf()");
checkValueInEachDoc(0, script, 6);
// check term frequencies for 'a'
script = createScript("term = _index['float_payload_field']['a']; if (term != null) {term.tf()}");
Map<String, Object> expectedResults = new HashMap<>();
expectedResults.put("1", 2);
expectedResults.put("2", 0);
expectedResults.put("3", 2);
expectedResults.put("4", 0);
expectedResults.put("5", 0);
expectedResults.put("6", 0);
checkValueInEachDoc(script, expectedResults, 6);
expectedResults.clear();
// check doc frequencies for 'c'
script = createScript("term = _index['float_payload_field']['c']; if (term != null) {term.df()}");
expectedResults.put("1", 1L);
expectedResults.put("2", 1L);
expectedResults.put("3", 1L);
expectedResults.put("4", 1L);
expectedResults.put("5", 1L);
expectedResults.put("6", 1L);
checkValueInEachDoc(script, expectedResults, 6);
expectedResults.clear();
// check doc frequencies for term that does not exist
script = createScript("term = _index['float_payload_field']['non_existent_term']; if (term != null) {term.df()}");
expectedResults.put("1", 0L);
expectedResults.put("2", 0L);
expectedResults.put("3", 0L);
expectedResults.put("4", 0L);
expectedResults.put("5", 0L);
expectedResults.put("6", 0L);
checkValueInEachDoc(script, expectedResults, 6);
expectedResults.clear();
// check doc frequencies for term that does not exist
script = createScript("term = _index['non_existent_field']['non_existent_term']; if (term != null) {term.tf()}");
expectedResults.put("1", 0);
expectedResults.put("2", 0);
expectedResults.put("3", 0);
expectedResults.put("4", 0);
expectedResults.put("5", 0);
expectedResults.put("6", 0);
checkValueInEachDoc(script, expectedResults, 6);
expectedResults.clear();
// check total term frequencies for 'a'
script = createScript("term = _index['float_payload_field']['a']; if (term != null) {term.ttf()}");
expectedResults.put("1", 4L);
expectedResults.put("2", 4L);
expectedResults.put("3", 4L);
expectedResults.put("4", 4L);
expectedResults.put("5", 4L);
expectedResults.put("6", 4L);
checkValueInEachDoc(script, expectedResults, 6);
expectedResults.clear();
// check float payload for 'b'
HashMap<String, List<Object>> expectedPayloadsArray = new HashMap<>();
script = createPositionsArrayScript("float_payload_field", "b", INCLUDE_ALL, "payloadAsFloat(-1)");
float missingValue = -1;
List<Object> payloadsFor1 = new ArrayList<>();
payloadsFor1.add(2f);
payloadsFor1.add(missingValue);
expectedPayloadsArray.put("1", payloadsFor1);
List<Object> payloadsFor2 = new ArrayList<>();
payloadsFor2.add(5f);
payloadsFor2.add(missingValue);
expectedPayloadsArray.put("3", payloadsFor2);
expectedPayloadsArray.put("6", new ArrayList<>());
expectedPayloadsArray.put("5", new ArrayList<>());
expectedPayloadsArray.put("4", new ArrayList<>());
expectedPayloadsArray.put("2", new ArrayList<>());
checkArrayValsInEachDoc(script, expectedPayloadsArray, 6);
// check string payload for 'b'
expectedPayloadsArray.clear();
payloadsFor1.clear();
payloadsFor2.clear();
script = createPositionsArrayScript("string_payload_field", "b", INCLUDE_ALL, "payloadAsString()");
payloadsFor1.add("b");
payloadsFor1.add(null);
expectedPayloadsArray.put("2", payloadsFor1);
payloadsFor2.add("a");
payloadsFor2.add(null);
expectedPayloadsArray.put("4", payloadsFor2);
expectedPayloadsArray.put("6", new ArrayList<>());
expectedPayloadsArray.put("5", new ArrayList<>());
expectedPayloadsArray.put("3", new ArrayList<>());
expectedPayloadsArray.put("1", new ArrayList<>());
checkArrayValsInEachDoc(script, expectedPayloadsArray, 6);
// check int payload for 'c'
expectedPayloadsArray.clear();
payloadsFor1.clear();
payloadsFor2.clear();
script = createPositionsArrayScript("int_payload_field", "c", INCLUDE_ALL, "payloadAsInt(-1)");
payloadsFor1 = new ArrayList<>();
payloadsFor1.add(1);
expectedPayloadsArray.put("6", payloadsFor1);
expectedPayloadsArray.put("5", new ArrayList<>());
expectedPayloadsArray.put("4", new ArrayList<>());
expectedPayloadsArray.put("3", new ArrayList<>());
expectedPayloadsArray.put("2", new ArrayList<>());
expectedPayloadsArray.put("1", new ArrayList<>());
checkArrayValsInEachDoc(script, expectedPayloadsArray, 6);
}
private void checkExceptions(Script script) {
try {
SearchResponse sr = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()).addScriptField("tvtest", script)
.execute().actionGet();
assertThat(sr.getHits().getHits().length, equalTo(0));
ShardSearchFailure[] shardFails = sr.getShardFailures();
for (ShardSearchFailure fail : shardFails) {
assertThat(fail.reason().indexOf("Cannot iterate twice! If you want to iterate more that once, add _CACHE explicitly."),
Matchers.greaterThan(-1));
}
} catch (SearchPhaseExecutionException ex) {
assertThat(
"got " + ex.toString(),
ex.toString().indexOf("Cannot iterate twice! If you want to iterate more that once, add _CACHE explicitly."),
Matchers.greaterThan(-1));
}
}
private void checkValueInEachDocWithFunctionScore(Script fieldScript, Map<String, Object> expectedFieldVals, Script scoreScript,
Map<String, Object> expectedScore, int numExpectedDocs) {
SearchResponse sr = client().prepareSearch("test")
.setQuery(QueryBuilders.functionScoreQuery(ScoreFunctionBuilders.scriptFunction(scoreScript)))
.addScriptField("tvtest", fieldScript).execute().actionGet();
assertHitCount(sr, numExpectedDocs);
for (SearchHit hit : sr.getHits().getHits()) {
Object result = hit.getFields().get("tvtest").getValues().get(0);
Object expectedResult = expectedFieldVals.get(hit.getId());
assertThat("for doc " + hit.getId(), result, equalTo(expectedResult));
assertThat("for doc " + hit.getId(), ((Float) expectedScore.get(hit.getId())).doubleValue(),
Matchers.closeTo(hit.getScore(), 1.e-4));
}
}
private void checkValueInEachDoc(Script script, Map<String, Object> expectedResults, int numExpectedDocs) {
SearchResponse sr = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()).addScriptField("tvtest", script)
.execute().actionGet();
assertHitCount(sr, numExpectedDocs);
for (SearchHit hit : sr.getHits().getHits()) {
Object result = hit.getFields().get("tvtest").getValues().get(0);
Object expectedResult = expectedResults.get(hit.getId());
assertThat("for doc " + hit.getId(), result, equalTo(expectedResult));
}
}
private void checkValueInEachDoc(int value, Script script, int numExpectedDocs) {
SearchResponse sr = client().prepareSearch("test").setQuery(QueryBuilders.matchAllQuery()).addScriptField("tvtest", script)
.execute().actionGet();
assertHitCount(sr, numExpectedDocs);
for (SearchHit hit : sr.getHits().getHits()) {
Object result = hit.getFields().get("tvtest").getValues().get(0);
if (result instanceof Integer) {
assertThat(result, equalTo(value));
} else if (result instanceof Long) {
assertThat(((Long) result).intValue(), equalTo(value));
} else {
fail();
}
}
}
}