@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); Query query = null; boolean queryFound = false; String parentType = null; String filterName = null; String currentFieldName = null; XContentParser.Token token; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { if ("query".equals(currentFieldName)) { // TODO handle `query` element before `type` element... String[] origTypes = QueryParseContext.setTypesWithPrevious( parentType == null ? null : new String[] {parentType}); try { query = parseContext.parseInnerQuery(); queryFound = true; } finally { QueryParseContext.setTypes(origTypes); } } else if ("filter".equals(currentFieldName)) { // TODO handle `filter` element before `type` element... String[] origTypes = QueryParseContext.setTypesWithPrevious( parentType == null ? null : new String[] {parentType}); try { Filter innerFilter = parseContext.parseInnerFilter(); query = new XConstantScoreQuery(innerFilter); queryFound = true; } finally { QueryParseContext.setTypes(origTypes); } } else { throw new QueryParsingException( parseContext.index(), "[has_parent] filter does not support [" + currentFieldName + "]"); } } else if (token.isValue()) { if ("type".equals(currentFieldName) || "parent_type".equals(currentFieldName) || "parentType".equals(currentFieldName)) { parentType = parser.text(); } else if ("_scope".equals(currentFieldName)) { throw new QueryParsingException( parseContext.index(), "the [_scope] support in [has_parent] filter has been removed, use a filter as a facet_filter in the relevant global facet"); } else if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else { throw new QueryParsingException( parseContext.index(), "[has_parent] filter does not support [" + currentFieldName + "]"); } } } if (!queryFound) { throw new QueryParsingException( parseContext.index(), "[parent] filter requires 'query' field"); } if (query == null) { return null; } if (parentType == null) { throw new QueryParsingException( parseContext.index(), "[parent] filter requires 'parent_type' field"); } DocumentMapper parentDocMapper = parseContext.mapperService().documentMapper(parentType); if (parentDocMapper == null) { throw new QueryParsingException( parseContext.index(), "[parent] filter configured 'parent_type' [" + parentType + "] is not a valid type"); } // wrap the query with type query query = new XFilteredQuery(query, parseContext.cacheFilter(parentDocMapper.typeFilter(), null)); SearchContext searchContext = SearchContext.current(); HasParentFilter parentFilter = HasParentFilter.create(query, parentType, searchContext); searchContext.addRewrite(parentFilter); if (filterName != null) { parseContext.addNamedFilter(filterName, parentFilter); } return parentFilter; }
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); String fieldName = null; boolean disableCoord = false; float boost = 1.0f; String minimumShouldMatch = null; List<String> values = newArrayList(); String currentFieldName = null; XContentParser.Token token; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_ARRAY) { fieldName = currentFieldName; while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { String value = parser.text(); if (value == null) { throw new QueryParsingException( parseContext.index(), "No value specified for terms query"); } values.add(value); } } else if (token.isValue()) { if ("disable_coord".equals(currentFieldName) || "disableCoord".equals(currentFieldName)) { disableCoord = parser.booleanValue(); } else if ("minimum_match".equals(currentFieldName) || "minimumMatch".equals(currentFieldName)) { minimumShouldMatch = parser.textOrNull(); } else if ("minimum_should_match".equals(currentFieldName) || "minimumShouldMatch".equals(currentFieldName)) { minimumShouldMatch = parser.textOrNull(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } } else { throw new QueryParsingException( parseContext.index(), "[terms] query does not support [" + currentFieldName + "]"); } } FieldMapper mapper = null; MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); String[] previousTypes = null; if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) { mapper = smartNameFieldMappers.mapper(); if (smartNameFieldMappers.explicitTypeInNameWithDocMapper()) { previousTypes = QueryParseContext.setTypesWithPrevious( new String[] {smartNameFieldMappers.docMapper().type()}); } } try { BooleanQuery query = new BooleanQuery(disableCoord); for (String value : values) { if (mapper != null) { query.add( new BooleanClause(mapper.termQuery(value, parseContext), BooleanClause.Occur.SHOULD)); } else { query.add(new TermQuery(new Term(fieldName, value)), BooleanClause.Occur.SHOULD); } } query.setBoost(boost); Queries.applyMinimumShouldMatch(query, minimumShouldMatch); return wrapSmartNameQuery( optimizeQuery(fixNegativeQueryIfNeeded(query)), smartNameFieldMappers, parseContext); } finally { if (smartNameFieldMappers != null && smartNameFieldMappers.explicitTypeInNameWithDocMapper()) { QueryParseContext.setTypes(previousTypes); } } }