Commit b636187a authored by Rustam Lotsmanenko (EPAM)'s avatar Rustam Lotsmanenko (EPAM)
Browse files

Merge branch 'bugfix-nested-query' into 'master'

Fix double path replacement for nested query

See merge request !128
parents d7c5b505 83966946
Pipeline #45968 passed with stages
in 34 minutes and 13 seconds
......@@ -86,9 +86,9 @@ public class QueryParserUtil implements IQueryParserUtil {
token = new StringBuilder();
}
height--;
if(height < 0){
if (height < 0) {
throw new AppException(HttpStatus.SC_BAD_REQUEST, "Malformed query",
String.format("Malformed closing parentheses in query part: \"%s\", at position: %d", queryString,position));
String.format("Malformed closing parentheses in query part: \"%s\", at position: %d", queryString, position));
}
} else if (height == 0 && token.length() > 0 && (andPositions.contains(position + 1) || orPositions.contains(position + 1))) {
tokens.add(token.toString());
......@@ -101,9 +101,9 @@ public class QueryParserUtil implements IQueryParserUtil {
tokens.add(token.toString());
}
if(height > 0){
if (height > 0) {
throw new AppException(HttpStatus.SC_BAD_REQUEST, "Malformed query",
String.format("Malformed parentheses in query part: \"%s\", %d of closing brackets missing", queryString,height));
String.format("Malformed parentheses in query part: \"%s\", %d of closing brackets missing", queryString, height));
}
return transformStringTokensToQueryNode(tokens);
......@@ -152,12 +152,12 @@ public class QueryParserUtil implements IQueryParserUtil {
Matcher beginQueryMatcher = beginStringQueryNestedPattern.matcher(stringQuery);
if (beginQueryMatcher.find()) {
String incompletePath = beginQueryMatcher.group(INCOMPLETE_PATH_GROUP);
stringQuery = stringQuery.replace(incompletePath, nestedPath + "." + incompletePath);
stringQuery = stringQuery.replaceFirst(incompletePath, nestedPath + "." + incompletePath);
}
Matcher stringQueryMatcher = intermediateStringQueryNestedPattern.matcher(stringQuery);
while (stringQueryMatcher.find()) {
String incompletePath = stringQueryMatcher.group(INCOMPLETE_PATH_GROUP);
stringQuery = stringQuery.replace(incompletePath, nestedPath + "." + incompletePath);
stringQuery = stringQuery.replaceFirst(incompletePath, nestedPath + "." + incompletePath);
}
stringQuery = trimTrailingBrackets(stringQuery);
return new NestedQueryNode(stringQuery, boolOperator, null, nestedPath);
......
package org.opengroup.osdu.search.util;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.nestedQuery;
import static org.elasticsearch.index.query.QueryBuilders.queryStringQuery;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.stream.JsonReader;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import org.apache.lucene.search.join.ScoreMode;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.junit.Rule;
import org.junit.Test;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
import org.opengroup.osdu.core.common.model.http.AppException;
@RunWith(Theories.class)
public class QueryParserUtilTest {
@Rule
public ExpectedException exceptionRule = ExpectedException.none();
private String simpleStringQuery = "simple query";
private String simpleQueryWithBools = "TEXAS OR TX";
private String combinedSimpleQueries = "(data.First:\"some data\") AND (data.Second:\"other data\")";
private String combinedSimpleAndNestedQuery =
"data.First:\"Example*\" OR nested(data.NestedTest, (StringTest:\"Example*\")) AND data.Second:\"test string\"";
private String expectedFirstStringQuery = "data.First:\"Example*\" ";
private String expectedNestedStringQuery = "(data.NestedTest.StringTest:\"Example*\")";
private String expectedSecondStringQuery = "data.Second:\"test string\"";
private String simpleNestedPath = "data.NestedTest";
private String simpleNestedQuery = "nested(" + simpleNestedPath + ", (NumberTest:(12345.0 OR 0) AND StringTest:\"test string\"))";
private String rangeSimpleNestedQuery = "nested(" + simpleNestedPath + ", (MarkerMeasuredDepth:(>0)))";
private String rangeSimpleCombinedNestedQuery = "nested(" + simpleNestedPath + ", (NumberTest:(>12345.0) AND SecondNumber:[0 TO 100]))";
private String expectedSimpleNestedQueryString =
"(" + simpleNestedPath + ".NumberTest:(12345.0 OR 0) AND " + simpleNestedPath + ".StringTest:\"test string\")";
private String expectedRangeSimpleCombinedNestedQueryString =
"(" + simpleNestedPath + ".NumberTest:(>12345.0) AND " + simpleNestedPath + ".SecondNumber:[0 TO 100])";
private String expectedRangeSimpleNestedQueryString = "(" + simpleNestedPath + ".MarkerMeasuredDepth:(>0))";
private String multilevelFirstLevelNestedPath = "data.FirstLevel";
private String multilevelSecondLevelNestedPath = "data.FirstLevel.SecondLevel";
private String multilevelThirdLevelNestedPath = "data.FirstLevel.SecondLevel.ThirdLevel";
private String queryStringForMultilevelNestedQuery = "(ThirdLevelNumberTest:\"12345.0\")";
private String expectedQueryStringForMultilevelNestedQuery = "(data.FirstLevel.SecondLevel.ThirdLevel.ThirdLevelNumberTest:\"12345.0\")";
private String multileveledNestedQuery =
"(nested(" + multilevelFirstLevelNestedPath +
", nested(" + multilevelSecondLevelNestedPath +
", nested(" + multilevelThirdLevelNestedPath + ", " + queryStringForMultilevelNestedQuery + "))))";
private String combinedParentNested = "data.ParentNested";
private String combinedFirstInnerNested = "data.ParentNested.FirstInnerNested";
private String combinedSecondInnerNested = "data.ParentNested.SecondInnerNested";
private String combinedMultilevelNestedQuery = "nested(" + combinedParentNested
+ ", nested(" + combinedFirstInnerNested + ", (NumberTest:(12345.0 OR 0) AND StringTest:\"test string\"))"
+ " OR nested(" + combinedSecondInnerNested + ", (NumberTest:\"12345.0\" AND StringTest:\"test string\")))";
private String expectedCombinedFirstInnerNestedQueryString =
"(" + combinedFirstInnerNested + ".NumberTest:(12345.0 OR 0) AND " + combinedFirstInnerNested + ".StringTest:\"test string\")";
private String expectedCombinedSecondInnerNestedQueryString =
"(" + combinedSecondInnerNested + ".NumberTest:\"12345.0\" AND " + combinedSecondInnerNested + ".StringTest:\"test string\")";
private String combinedNestedQueryWithNot = "nested(" + combinedParentNested
+ ", nested(" + combinedFirstInnerNested + ", (NumberTest:(12345.0 OR 0) AND StringTest:\"test string\"))"
+ " NOT nested(" + combinedSecondInnerNested + ", (NumberTest:\"12345.0\" AND StringTest:\"test string\")))";
private String incompleteParenthesesQuery = "nested(" + simpleNestedPath + ", (NumberTest:(12345.0 OR 0) AND StringTest:\"test string\"";
private String malformedParenthesesQuery = "nested(" + simpleNestedPath + ", ))NumberTest:(12345.0 OR 0) AND StringTest:\"test string\"))";
private QueryParserUtil queryParserUtil = new QueryParserUtil();
@Test
public void shouldReturnQueryBuilderWithSimpleQuery() {
BoolQueryBuilder queryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(simpleStringQuery);
List<QueryBuilder> mustQueries = queryBuilder.must();
QueryStringQueryBuilder stringQueryBuilder = (QueryStringQueryBuilder) mustQueries.get(0);
assertNotNull(stringQueryBuilder);
assertEquals(simpleStringQuery, stringQueryBuilder.queryString());
@DataPoints("VALID_QUERIES")
public static List<ImmutablePair> validQueriesList() {
InputStream inStream = QueryParserUtilTest.class.getResourceAsStream("/testqueries/valid-queries.json");
return getPairsFromFile(inStream);
}
@Test
public void shouldReturnSingleQueryBuilderFormSimpleQueryWithBool() {
BoolQueryBuilder queryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(simpleQueryWithBools);
List<QueryBuilder> mustQueries = queryBuilder.must();
assertEquals(1, mustQueries.size());
QueryStringQueryBuilder stringQueryBuilder = (QueryStringQueryBuilder) mustQueries.get(0);
assertNotNull(stringQueryBuilder);
assertEquals(simpleQueryWithBools, stringQueryBuilder.queryString());
@DataPoints("NOT_VALID_QUERIES")
public static List<ImmutablePair> notValidQueriesList() {
InputStream inStream = QueryParserUtilTest.class.getResourceAsStream("/testqueries/not-valid-queries.json");
return getPairsFromFile(inStream);
}
@Test
public void shouldReturnSingleQueryBuilderForCombinedQuery() {
BoolQueryBuilder queryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(combinedSimpleQueries);
List<QueryBuilder> mustQueries = queryBuilder.must();
assertEquals(1, mustQueries.size());
QueryStringQueryBuilder stringQueryBuilder = (QueryStringQueryBuilder) mustQueries.get(0);
assertEquals(combinedSimpleQueries, stringQueryBuilder.queryString());
@Theory
public void shouldReturnQueryBuilderForValidQueries(@FromDataPoints("VALID_QUERIES") ImmutablePair<String, String> pair) {
BoolQueryBuilder queryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(pair.getValue());
JsonObject expectedQuery = getExpectedQuery(pair.getKey());
JsonParser jsonParser = new JsonParser();
JsonObject actualQuery = jsonParser.parse(queryBuilder.toString()).getAsJsonObject();
assertEquals(expectedQuery, actualQuery);
}
@Test
public void shouldReturnCombinedNestedAndSimpleQueryBuilder() {
BoolQueryBuilder actualBoolQueryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(combinedSimpleAndNestedQuery);
List<QueryBuilder> must = actualBoolQueryBuilder.must();
assertEquals(1, must.size());
QueryStringQueryBuilder expectedFirstQuery = queryStringQuery(expectedFirstStringQuery).allowLeadingWildcard(false);
NestedQueryBuilder expectedNestedQuery =
nestedQuery(simpleNestedPath, queryStringQuery(expectedNestedStringQuery).allowLeadingWildcard(false), ScoreMode.Avg);
QueryStringQueryBuilder expectedSecondQuery = queryStringQuery(expectedSecondStringQuery).allowLeadingWildcard(false);
BoolQueryBuilder expected = boolQuery().should(expectedFirstQuery).should(expectedNestedQuery).must(expectedSecondQuery);
assertEquals(expected, actualBoolQueryBuilder);
}
@Test
public void shouldReturnNestedQueryBuilderForNestedQuery() {
BoolQueryBuilder queryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(simpleNestedQuery);
List<QueryBuilder> mustQueries = queryBuilder.must();
assertEquals(1, mustQueries.size());
NestedQueryBuilder nestedQueryBuilder = (NestedQueryBuilder) mustQueries.get(0);
NestedQueryBuilder expectedNestedQuery =
nestedQuery(simpleNestedPath, queryStringQuery(expectedSimpleNestedQueryString).allowLeadingWildcard(false), ScoreMode.Avg);
assertEquals(expectedNestedQuery, nestedQueryBuilder);
}
@Test
public void shouldReturnNestedQueryBuilderForRangeNestedQuery() {
BoolQueryBuilder boolQueryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(rangeSimpleNestedQuery);
List<QueryBuilder> mustQueries = boolQueryBuilder.must();
assertEquals(1, mustQueries.size());
NestedQueryBuilder nestedQueryBuilder = (NestedQueryBuilder) mustQueries.get(0);
NestedQueryBuilder expectedNestedQuery =
nestedQuery(simpleNestedPath, queryStringQuery(expectedRangeSimpleNestedQueryString).allowLeadingWildcard(false), ScoreMode.Avg);
assertEquals(expectedNestedQuery, nestedQueryBuilder);
}
@Test
public void shouldReturnNestedQueryBuilderForCombinedRangeNestedQuery() {
BoolQueryBuilder boolQueryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(rangeSimpleCombinedNestedQuery);
List<QueryBuilder> mustQueries = boolQueryBuilder.must();
assertEquals(1, mustQueries.size());
NestedQueryBuilder nestedQueryBuilder = (NestedQueryBuilder) mustQueries.get(0);
NestedQueryBuilder expectedNestedQuery =
nestedQuery(simpleNestedPath, queryStringQuery(expectedRangeSimpleCombinedNestedQueryString).allowLeadingWildcard(false), ScoreMode.Avg);
assertEquals(expectedNestedQuery, nestedQueryBuilder);
}
@Test
public void shouldReturnCombinedMultilevelNestedQuery() {
BoolQueryBuilder queryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(combinedMultilevelNestedQuery);
List<QueryBuilder> mustQueries = queryBuilder.must();
assertEquals(1, mustQueries.size());
NestedQueryBuilder parentNestedQueryBuilder = (NestedQueryBuilder) mustQueries.get(0);
BoolQueryBuilder boolNestedQueryBuilder = (BoolQueryBuilder) parentNestedQueryBuilder.query();
List<QueryBuilder> innerShould = boolNestedQueryBuilder.should();
assertEquals(2, innerShould.size());
NestedQueryBuilder firstInnerNestedQuery = (NestedQueryBuilder) innerShould.get(0);
NestedQueryBuilder secondInnerNestedQuery = (NestedQueryBuilder) innerShould.get(1);
NestedQueryBuilder expectedFirstInnerNestedQuery =
nestedQuery(combinedFirstInnerNested, queryStringQuery(expectedCombinedFirstInnerNestedQueryString).allowLeadingWildcard(false), ScoreMode.Avg);
NestedQueryBuilder expectedSecondInnerNestedQuery =
nestedQuery(combinedSecondInnerNested, queryStringQuery(expectedCombinedSecondInnerNestedQueryString).allowLeadingWildcard(false), ScoreMode.Avg);
assertEquals(expectedFirstInnerNestedQuery, firstInnerNestedQuery);
assertEquals(expectedSecondInnerNestedQuery, secondInnerNestedQuery);
}
@Test
public void shouldReturnMultilevelNestedQuery() {
BoolQueryBuilder boolQueryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(multileveledNestedQuery);
List<QueryBuilder> must = boolQueryBuilder.must();
assertEquals(1, must.size());
NestedQueryBuilder firstLevel = (NestedQueryBuilder) must.get(0);
NestedQueryBuilder expectedThirdLevel =
nestedQuery(multilevelThirdLevelNestedPath, queryStringQuery(expectedQueryStringForMultilevelNestedQuery).allowLeadingWildcard(false),
ScoreMode.Avg);
NestedQueryBuilder expectedSecondLevel = nestedQuery(multilevelSecondLevelNestedPath, boolQuery().must(expectedThirdLevel), ScoreMode.Avg);
NestedQueryBuilder expectedFirstLevel = nestedQuery(multilevelFirstLevelNestedPath, boolQuery().must(expectedSecondLevel), ScoreMode.Avg);
assertEquals(expectedFirstLevel, firstLevel);
}
@Test
public void shouldReturnMustAndMustNotQueryBuilderForQueryWithNot() {
BoolQueryBuilder boolQueryBuilder = (BoolQueryBuilder) queryParserUtil.buildQueryBuilderFromQueryString(combinedNestedQueryWithNot);
List<QueryBuilder> must = boolQueryBuilder.must();
assertEquals(1, must.size());
NestedQueryBuilder parentNestedQueryBuilder = (NestedQueryBuilder) must.get(0);
BoolQueryBuilder boolNestedQueryBuilder = (BoolQueryBuilder) parentNestedQueryBuilder.query();
List<QueryBuilder> innerMust = boolNestedQueryBuilder.must();
assertEquals(1, innerMust.size());
List<QueryBuilder> innerMustNot = boolNestedQueryBuilder.mustNot();
assertEquals(1, innerMustNot.size());
NestedQueryBuilder MustInnerNestedQuery = (NestedQueryBuilder) innerMust.get(0);
NestedQueryBuilder MustNotInnerNestedQuery = (NestedQueryBuilder) innerMustNot.get(0);
NestedQueryBuilder expectedFirstInnerNestedQuery =
nestedQuery(combinedFirstInnerNested, queryStringQuery(expectedCombinedFirstInnerNestedQueryString).allowLeadingWildcard(false), ScoreMode.Avg);
NestedQueryBuilder expectedSecondInnerNestedQuery =
nestedQuery(combinedSecondInnerNested, queryStringQuery(expectedCombinedSecondInnerNestedQueryString).allowLeadingWildcard(false), ScoreMode.Avg);
assertEquals(expectedFirstInnerNestedQuery, MustInnerNestedQuery);
assertEquals(expectedSecondInnerNestedQuery, MustNotInnerNestedQuery);
@Theory
public void shouldThrowExceptionForNotValidQueries(@FromDataPoints("NOT_VALID_QUERIES") ImmutablePair<String, String> pair) {
exceptionRule.expect(AppException.class);
exceptionRule.expectMessage(pair.getKey());
queryParserUtil.buildQueryBuilderFromQueryString(pair.getValue());
}
@Test
public void shouldThrowAppExceptionWhenParenthesesIncomplete() {
exceptionRule.expect(AppException.class);
exceptionRule.expectMessage("2 of closing brackets missing");
queryParserUtil.buildQueryBuilderFromQueryString(incompleteParenthesesQuery);
private static List<ImmutablePair> getPairsFromFile(InputStream inStream) {
BufferedReader br = new BufferedReader(new InputStreamReader(inStream));
Gson gson = new Gson();
JsonReader reader = new JsonReader(br);
Map<String, String> queriesMap = gson.fromJson(reader, Map.class);
List<ImmutablePair> pairs =
queriesMap.entrySet().stream().map(entry -> new ImmutablePair(entry.getKey(), entry.getValue())).collect(Collectors.toList());
return pairs;
}
@Test
public void shouldThrowAppExceptionWhenParenthesesMalformed() {
exceptionRule.expect(AppException.class);
exceptionRule.expectMessage("Malformed closing parentheses in query part:");
exceptionRule.expectMessage("at position: 25");
queryParserUtil.buildQueryBuilderFromQueryString(malformedParenthesesQuery);
private JsonObject getExpectedQuery(String queryFile) {
InputStream inStream = this.getClass().getResourceAsStream("/testqueries/expected/" + queryFile + ".json");
BufferedReader br = new BufferedReader(new InputStreamReader(inStream));
Gson gson = new Gson();
JsonReader reader = new JsonReader(br);
return gson.fromJson(reader, JsonObject.class);
}
}
\ No newline at end of file
{
"bool": {
"must": [
{
"nested": {
"query": {
"bool": {
"should": [
{
"nested": {
"query": {
"query_string": {
"query": "(data.ParentNested.FirstInnerNested.NumberTest:(12345.0 OR 0) AND data.ParentNested.FirstInnerNested.StringTest:\"test string\")",
"fields": [],
"type": "best_fields",
"default_operator": "or",
"max_determinized_states": 10000,
"allow_leading_wildcard": false,
"enable_position_increments": true,
"fuzziness": "AUTO",
"fuzzy_prefix_length": 0,
"fuzzy_max_expansions": 50,
"phrase_slop": 0,
"escape": false,
"auto_generate_synonyms_phrase_query": true,
"fuzzy_transpositions": true,
"boost": 1.0
}
},
"path": "data.ParentNested.FirstInnerNested",
"ignore_unmapped": false,
"score_mode": "avg",
"boost": 1.0
}
},
{
"nested": {
"query": {
"query_string": {
"query": "(data.ParentNested.SecondInnerNested.NumberTest:\"12345.0\" AND data.ParentNested.SecondInnerNested.StringTest:\"test string\")",
"fields": [],
"type": "best_fields",
"default_operator": "or",
"max_determinized_states": 10000,
"allow_leading_wildcard": false,
"enable_position_increments": true,
"fuzziness": "AUTO",
"fuzzy_prefix_length": 0,
"fuzzy_max_expansions": 50,
"phrase_slop": 0,
"escape": false,
"auto_generate_synonyms_phrase_query": true,
"fuzzy_transpositions": true,
"boost": 1.0
}
},
"path": "data.ParentNested.SecondInnerNested",
"ignore_unmapped": false,
"score_mode": "avg",
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"path": "data.ParentNested",
"ignore_unmapped": false,
"score_mode": "avg",
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
}
\ No newline at end of file
{
"bool": {
"must": [
{
"nested": {
"query": {
"bool": {
"must": [
{
"nested": {
"query": {
"query_string": {
"query": "(data.ParentNested.FirstInnerNested.NumberTest:(12345.0 OR 0) AND data.ParentNested.FirstInnerNested.StringTest:\"test string\")",
"fields": [],
"type": "best_fields",
"default_operator": "or",
"max_determinized_states": 10000,
"allow_leading_wildcard": false,
"enable_position_increments": true,
"fuzziness": "AUTO",
"fuzzy_prefix_length": 0,
"fuzzy_max_expansions": 50,
"phrase_slop": 0,
"escape": false,
"auto_generate_synonyms_phrase_query": true,
"fuzzy_transpositions": true,
"boost": 1.0
}
},
"path": "data.ParentNested.FirstInnerNested",
"ignore_unmapped": false,
"score_mode": "avg",
"boost": 1.0
}
}
],
"must_not": [
{
"nested": {
"query": {
"query_string": {
"query": "(data.ParentNested.SecondInnerNested.NumberTest:\"12345.0\" AND data.ParentNested.SecondInnerNested.StringTest:\"test string\")",
"fields": [],
"type": "best_fields",
"default_operator": "or",
"max_determinized_states": 10000,
"allow_leading_wildcard": false,
"enable_position_increments": true,
"fuzziness": "AUTO",
"fuzzy_prefix_length": 0,
"fuzzy_max_expansions": 50,
"phrase_slop": 0,
"escape": false,
"auto_generate_synonyms_phrase_query": true,
"fuzzy_transpositions": true,
"boost": 1.0
}
},
"path": "data.ParentNested.SecondInnerNested",
"ignore_unmapped": false,
"score_mode": "avg",
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
},
"path": "data.ParentNested",
"ignore_unmapped": false,
"score_mode": "avg",
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
}
\ No newline at end of file
{
"bool": {
"must": [
{
"nested": {
"query": {
"query_string": {
"query": "(data.NestedTest.NumberTest:(>12345.0) AND data.NestedTest.SecondNumber:[0 TO 100])",
"fields": [],
"type": "best_fields",
"default_operator": "or",
"max_determinized_states": 10000,
"allow_leading_wildcard": false,
"enable_position_increments": true,
"fuzziness": "AUTO",
"fuzzy_prefix_length": 0,
"fuzzy_max_expansions": 50,
"phrase_slop": 0,
"escape": false,
"auto_generate_synonyms_phrase_query": true,
"fuzzy_transpositions": true,
"boost": 1.0
}
},
"path": "data.NestedTest",
"ignore_unmapped": false,
"score_mode": "avg",
"boost": 1.0
}
}
],
"adjust_pure_negative": true,
"boost": 1.0
}
}
\ No newline at end of file