public static Filter newFilter( QueryParseContext parseContext, String fieldPattern, String filterName) { final FieldMappers fieldNamesMappers = parseContext.mapperService().indexName(FieldNamesFieldMapper.NAME); final FieldNamesFieldMapper fieldNamesMapper = fieldNamesMappers == null ? null : (FieldNamesFieldMapper) fieldNamesMappers.mapper(); MapperService.SmartNameObjectMapper smartNameObjectMapper = parseContext.smartObjectMapper(fieldPattern); if (smartNameObjectMapper != null && smartNameObjectMapper.hasMapper()) { // automatic make the object mapper pattern fieldPattern = fieldPattern + ".*"; } List<String> fields = parseContext.simpleMatchToIndexNames(fieldPattern); if (fields.isEmpty()) { // no fields exists, so we should not match anything return Queries.MATCH_NO_FILTER; } MapperService.SmartNameFieldMappers nonNullFieldMappers = null; XBooleanFilter boolFilter = new XBooleanFilter(); for (String field : fields) { MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(field); if (smartNameFieldMappers != null) { nonNullFieldMappers = smartNameFieldMappers; } Filter filter = null; if (fieldNamesMapper != null && fieldNamesMapper.enabled()) { final String f; if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) { f = smartNameFieldMappers.mapper().names().indexName(); } else { f = field; } filter = fieldNamesMapper.termFilter(f, parseContext); } // if _field_names are not indexed, we need to go the slow way if (filter == null && smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) { filter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true, parseContext); } if (filter == null) { filter = new TermRangeFilter(field, null, null, true, true); } boolFilter.add(filter, BooleanClause.Occur.SHOULD); } // we always cache this one, really does not change... (exists) // its ok to cache under the fieldName cacheKey, since its per segment and the mapping applies // to this data on this segment... Filter filter = parseContext.cacheFilter(boolFilter, new CacheKeyFilter.Key("$exists$" + fieldPattern)); filter = wrapSmartNameFilter(filter, nonNullFieldMappers, parseContext); if (filterName != null) { parseContext.addNamedFilter(filterName, filter); } return filter; }
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); Query query = null; boolean queryFound = false; Filter filter = null; boolean filterFound = false; float boost = 1.0f; boolean cache = false; CacheKeyFilter.Key cacheKey = null; String currentFieldName = null; XContentParser.Token token; FilteredQuery.FilterStrategy filterStrategy = XFilteredQuery.CUSTOM_FILTER_STRATEGY; 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)) { queryFound = true; query = parseContext.parseInnerQuery(); } else if ("filter".equals(currentFieldName)) { filterFound = true; filter = parseContext.parseInnerFilter(); } else { throw new QueryParsingException( parseContext.index(), "[filtered] query does not support [" + currentFieldName + "]"); } } else if (token.isValue()) { if ("strategy".equals(currentFieldName)) { String value = parser.text(); if ("query_first".equals(value) || "queryFirst".equals(value)) { filterStrategy = FilteredQuery.QUERY_FIRST_FILTER_STRATEGY; } else if ("random_access_random".equals(value) || "randomAccessAlways".equals(value)) { filterStrategy = XFilteredQuery.ALWAYS_RANDOM_ACCESS_FILTER_STRATEGY; } else if ("leap_frog".equals(value) || "leapFrog".equals(value)) { filterStrategy = FilteredQuery.LEAP_FROG_QUERY_FIRST_STRATEGY; } else if (value.startsWith("random_access_")) { int threshold = Integer.parseInt(value.substring("random_access_".length())); filterStrategy = new XFilteredQuery.CustomRandomAccessFilterStrategy(threshold); } else if (value.startsWith("randomAccess")) { int threshold = Integer.parseInt(value.substring("randomAccess".length())); filterStrategy = new XFilteredQuery.CustomRandomAccessFilterStrategy(threshold); } else if ("leap_frog_query_first".equals(value) || "leapFrogQueryFirst".equals(value)) { filterStrategy = FilteredQuery.LEAP_FROG_QUERY_FIRST_STRATEGY; } else if ("leap_frog_filter_first".equals(value) || "leapFrogFilterFirst".equals(value)) { filterStrategy = FilteredQuery.LEAP_FROG_FILTER_FIRST_STRATEGY; } else { throw new QueryParsingException( parseContext.index(), "[filtered] strategy value not supported [" + value + "]"); } } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("_cache".equals(currentFieldName)) { cache = parser.booleanValue(); } else if ("_cache_key".equals(currentFieldName) || "_cacheKey".equals(currentFieldName)) { cacheKey = new CacheKeyFilter.Key(parser.text()); } else { throw new QueryParsingException( parseContext.index(), "[filtered] query does not support [" + currentFieldName + "]"); } } } if (!queryFound) { throw new QueryParsingException(parseContext.index(), "[filtered] requires 'query' element"); } if (query == null) { return null; } if (filter == null) { if (!filterFound) { // we allow for null filter, so it makes compositions on the client side to be simpler return query; } else { // the filter was provided, but returned null, meaning we should discard it, this means no // matches for this query... return Queries.NO_MATCH_QUERY; } } if (filter == Queries.MATCH_ALL_FILTER) { // this is an instance of match all filter, just execute the query return query; } // cache if required if (cache) { filter = parseContext.cacheFilter(filter, cacheKey); } // if its a match_all query, use constant_score if (Queries.isConstantMatchAllQuery(query)) { Query q = new XConstantScoreQuery(filter); q.setBoost(boost); return q; } XFilteredQuery filteredQuery = new XFilteredQuery(query, filter, filterStrategy); filteredQuery.setBoost(boost); return filteredQuery; }
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { ensureNotDeleteByQuery(NAME, parseContext); XContentParser parser = parseContext.parser(); boolean queryFound = false; float boost = 1.0f; String childType = null; ScoreType scoreType = ScoreType.NONE; int minChildren = 0; int maxChildren = 0; int shortCircuitParentDocSet = 8192; String queryName = null; Tuple<String, SubSearchContext> innerHits = null; String currentFieldName = null; XContentParser.Token token; XContentStructure.InnerQuery iq = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { // Usually, the query would be parsed here, but the child // type may not have been extracted yet, so use the // XContentStructure.<type> facade to parse if available, // or delay parsing if not. if ("query".equals(currentFieldName)) { iq = new XContentStructure.InnerQuery( parseContext, childType == null ? null : new String[] {childType}); queryFound = true; } else if ("inner_hits".equals(currentFieldName)) { innerHits = innerHitsQueryParserHelper.parse(parseContext); } else { throw new QueryParsingException( parseContext.index(), "[has_child] query does not support [" + currentFieldName + "]"); } } else if (token.isValue()) { if ("type".equals(currentFieldName) || "child_type".equals(currentFieldName) || "childType".equals(currentFieldName)) { childType = parser.text(); } else if ("score_type".equals(currentFieldName) || "scoreType".equals(currentFieldName)) { scoreType = ScoreType.fromString(parser.text()); } else if ("score_mode".equals(currentFieldName) || "scoreMode".equals(currentFieldName)) { scoreType = ScoreType.fromString(parser.text()); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("min_children".equals(currentFieldName) || "minChildren".equals(currentFieldName)) { minChildren = parser.intValue(true); } else if ("max_children".equals(currentFieldName) || "maxChildren".equals(currentFieldName)) { maxChildren = parser.intValue(true); } else if ("short_circuit_cutoff".equals(currentFieldName)) { shortCircuitParentDocSet = parser.intValue(); } else if ("_name".equals(currentFieldName)) { queryName = parser.text(); } else { throw new QueryParsingException( parseContext.index(), "[has_child] query does not support [" + currentFieldName + "]"); } } } if (!queryFound) { throw new QueryParsingException(parseContext.index(), "[has_child] requires 'query' field"); } if (childType == null) { throw new QueryParsingException(parseContext.index(), "[has_child] requires 'type' field"); } Query innerQuery = iq.asQuery(childType); if (innerQuery == null) { return null; } innerQuery.setBoost(boost); DocumentMapper childDocMapper = parseContext.mapperService().documentMapper(childType); if (childDocMapper == null) { throw new QueryParsingException( parseContext.index(), "[has_child] No mapping for for type [" + childType + "]"); } if (!childDocMapper.parentFieldMapper().active()) { throw new QueryParsingException( parseContext.index(), "[has_child] Type [" + childType + "] does not have parent mapping"); } if (innerHits != null) { InnerHitsContext.ParentChildInnerHits parentChildInnerHits = new InnerHitsContext.ParentChildInnerHits( innerHits.v2(), innerQuery, null, childDocMapper); String name = innerHits.v1() != null ? innerHits.v1() : childType; parseContext.addInnerHits(name, parentChildInnerHits); } ParentFieldMapper parentFieldMapper = childDocMapper.parentFieldMapper(); if (!parentFieldMapper.active()) { throw new QueryParsingException( parseContext.index(), "[has_child] _parent field not configured"); } String parentType = parentFieldMapper.type(); DocumentMapper parentDocMapper = parseContext.mapperService().documentMapper(parentType); if (parentDocMapper == null) { throw new QueryParsingException( parseContext.index(), "[has_child] Type [" + childType + "] points to a non existent parent type [" + parentType + "]"); } if (maxChildren > 0 && maxChildren < minChildren) { throw new QueryParsingException( parseContext.index(), "[has_child] 'max_children' is less than 'min_children'"); } BitDocIdSetFilter nonNestedDocsFilter = null; if (parentDocMapper.hasNestedObjects()) { nonNestedDocsFilter = parseContext.bitsetFilter(NonNestedDocsFilter.INSTANCE); } // wrap the query with type query innerQuery = new FilteredQuery( innerQuery, parseContext.cacheFilter( childDocMapper.typeFilter(), null, parseContext.autoFilterCachePolicy())); Query query; Filter parentFilter = parseContext.cacheFilter( parentDocMapper.typeFilter(), null, parseContext.autoFilterCachePolicy()); ParentChildIndexFieldData parentChildIndexFieldData = parseContext.getForField(parentFieldMapper); if (minChildren > 1 || maxChildren > 0 || scoreType != ScoreType.NONE) { query = new ChildrenQuery( parentChildIndexFieldData, parentType, childType, parentFilter, innerQuery, scoreType, minChildren, maxChildren, shortCircuitParentDocSet, nonNestedDocsFilter); } else { query = new ChildrenConstantScoreQuery( parentChildIndexFieldData, innerQuery, parentType, childType, parentFilter, shortCircuitParentDocSet, nonNestedDocsFilter); } if (queryName != null) { parseContext.addNamedFilter(queryName, new CustomQueryWrappingFilter(query)); } query.setBoost(boost); return query; }
@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); String fieldName = null; String filterName = null; boolean nullValue = false; boolean existence = true; XContentParser.Token token; String currentFieldName = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token.isValue()) { if ("field".equals(currentFieldName)) { fieldName = parser.text(); } else if ("null_value".equals(currentFieldName)) { nullValue = parser.booleanValue(); } else if ("existence".equals(currentFieldName)) { existence = parser.booleanValue(); } else if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else { throw new QueryParsingException( parseContext.index(), "[missing] filter does not support [" + currentFieldName + "]"); } } } if (fieldName == null) { throw new QueryParsingException( parseContext.index(), "missing must be provided with a [field]"); } if (!existence && !nullValue) { throw new QueryParsingException( parseContext.index(), "missing must have either existence, or null_value, or both set to true"); } Filter existenceFilter = null; Filter nullFilter = null; MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); if (existence) { if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) { existenceFilter = smartNameFieldMappers.mapper().rangeFilter(null, null, true, true, parseContext); } if (existenceFilter == null) { existenceFilter = new TermRangeFilter(fieldName, null, null, true, true); } // we always cache this one, really does not change... (exists) existenceFilter = parseContext.cacheFilter(existenceFilter, null); existenceFilter = new NotFilter(existenceFilter); // cache the not filter as well, so it will be faster existenceFilter = parseContext.cacheFilter(existenceFilter, null); } if (nullValue) { if (smartNameFieldMappers != null && smartNameFieldMappers.hasMapper()) { nullFilter = smartNameFieldMappers.mapper().nullValueFilter(); if (nullFilter != null) { // cache the not filter as well, so it will be faster nullFilter = parseContext.cacheFilter(nullFilter, null); } } } Filter filter; if (nullFilter != null) { if (existenceFilter != null) { XBooleanFilter combined = new XBooleanFilter(); combined.addShould(existenceFilter); combined.addShould(nullFilter); // cache the not filter as well, so it will be faster filter = parseContext.cacheFilter(combined, null); } else { filter = nullFilter; } } else { filter = existenceFilter; } if (filter == null) { return null; } filter = wrapSmartNameFilter(filter, smartNameFieldMappers, parseContext); if (filterName != null) { parseContext.addNamedFilter(filterName, existenceFilter); } return filter; }
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); Query query = Queries.newMatchAllQuery(); Filter filter = null; boolean filterFound = false; float boost = 1.0f; FilterCachingPolicy cache = parseContext.autoFilterCachePolicy(); HashedBytesRef cacheKey = null; String queryName = null; String currentFieldName = null; XContentParser.Token token; FilteredQuery.FilterStrategy filterStrategy = CUSTOM_FILTER_STRATEGY; 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)) { query = parseContext.parseInnerQuery(); } else if ("filter".equals(currentFieldName)) { filterFound = true; filter = parseContext.parseInnerFilter(); } else { throw new QueryParsingException( parseContext.index(), "[filtered] query does not support [" + currentFieldName + "]"); } } else if (token.isValue()) { if ("strategy".equals(currentFieldName)) { String value = parser.text(); if ("query_first".equals(value) || "queryFirst".equals(value)) { filterStrategy = FilteredQuery.QUERY_FIRST_FILTER_STRATEGY; } else if ("random_access_always".equals(value) || "randomAccessAlways".equals(value)) { filterStrategy = ALWAYS_RANDOM_ACCESS_FILTER_STRATEGY; } else if ("leap_frog".equals(value) || "leapFrog".equals(value)) { filterStrategy = FilteredQuery.LEAP_FROG_QUERY_FIRST_STRATEGY; } else if (value.startsWith("random_access_")) { int threshold = Integer.parseInt(value.substring("random_access_".length())); filterStrategy = new CustomRandomAccessFilterStrategy(threshold); } else if (value.startsWith("randomAccess")) { int threshold = Integer.parseInt(value.substring("randomAccess".length())); filterStrategy = new CustomRandomAccessFilterStrategy(threshold); } else if ("leap_frog_query_first".equals(value) || "leapFrogQueryFirst".equals(value)) { filterStrategy = FilteredQuery.LEAP_FROG_QUERY_FIRST_STRATEGY; } else if ("leap_frog_filter_first".equals(value) || "leapFrogFilterFirst".equals(value)) { filterStrategy = FilteredQuery.LEAP_FROG_FILTER_FIRST_STRATEGY; } else { throw new QueryParsingException( parseContext.index(), "[filtered] strategy value not supported [" + value + "]"); } } else if ("_name".equals(currentFieldName)) { queryName = parser.text(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("_cache".equals(currentFieldName)) { cache = parseContext.parseFilterCachePolicy(); } else if ("_cache_key".equals(currentFieldName) || "_cacheKey".equals(currentFieldName)) { cacheKey = new HashedBytesRef(parser.text()); } else { throw new QueryParsingException( parseContext.index(), "[filtered] query does not support [" + currentFieldName + "]"); } } } // parsed internally, but returned null during parsing... if (query == null) { return null; } if (filter == null) { if (!filterFound) { // we allow for null filter, so it makes compositions on the client side to be simpler return query; } else { // even if the filter is not found, and its null, we should simply ignore it, and go // by the query return query; } } if (filter == Queries.MATCH_ALL_FILTER) { // this is an instance of match all filter, just execute the query return query; } // cache if required if (cache != null) { filter = parseContext.cacheFilter(filter, cacheKey, cache); } // if its a match_all query, use constant_score if (Queries.isConstantMatchAllQuery(query)) { Query q = new ConstantScoreQuery(filter); q.setBoost(boost); return q; } FilteredQuery filteredQuery = new FilteredQuery(query, filter, filterStrategy); filteredQuery.setBoost(boost); if (queryName != null) { parseContext.addNamedQuery(queryName, filteredQuery); } return filteredQuery; }
@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); boolean cache = true; CacheKeyFilter.Key cacheKey = null; String fieldName = null; Object from = null; Object to = null; boolean includeLower = true; boolean includeUpper = true; 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) { fieldName = currentFieldName; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else { if ("from".equals(currentFieldName)) { from = parser.objectBytes(); } else if ("to".equals(currentFieldName)) { to = parser.objectBytes(); } else if ("include_lower".equals(currentFieldName) || "includeLower".equals(currentFieldName)) { includeLower = parser.booleanValue(); } else if ("include_upper".equals(currentFieldName) || "includeUpper".equals(currentFieldName)) { includeUpper = parser.booleanValue(); } else if ("gt".equals(currentFieldName)) { from = parser.objectBytes(); includeLower = false; } else if ("gte".equals(currentFieldName) || "ge".equals(currentFieldName)) { from = parser.objectBytes(); includeLower = true; } else if ("lt".equals(currentFieldName)) { to = parser.objectBytes(); includeUpper = false; } else if ("lte".equals(currentFieldName) || "le".equals(currentFieldName)) { to = parser.objectBytes(); includeUpper = true; } else { throw new QueryParsingException( parseContext.index(), "[range] filter does not support [" + currentFieldName + "]"); } } } } else if (token.isValue()) { if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else if ("_cache".equals(currentFieldName)) { cache = parser.booleanValue(); } else if ("_cache_key".equals(currentFieldName) || "_cacheKey".equals(currentFieldName)) { cacheKey = new CacheKeyFilter.Key(parser.text()); } else { throw new QueryParsingException( parseContext.index(), "[range] filter does not support [" + currentFieldName + "]"); } } } if (fieldName == null) { throw new QueryParsingException(parseContext.index(), "No field specified for range filter"); } Filter filter = null; MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); if (smartNameFieldMappers != null) { if (smartNameFieldMappers.hasMapper()) { filter = smartNameFieldMappers .mapper() .rangeFilter(from, to, includeLower, includeUpper, parseContext); } } if (filter == null) { filter = new TermRangeFilter( fieldName, BytesRefs.toBytesRef(from), BytesRefs.toBytesRef(to), includeLower, includeUpper); } if (cache) { filter = parseContext.cacheFilter(filter, cacheKey); } filter = wrapSmartNameFilter(filter, smartNameFieldMappers, parseContext); if (filterName != null) { parseContext.addNamedFilter(filterName, filter); } return filter; }
/* (non-Javadoc) * @see cn.com.rebirth.search.core.index.query.FilterParser#parse(cn.com.rebirth.search.core.index.query.QueryParseContext) */ @Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); XContentParser.Token token; boolean cache = false; CacheKeyFilter.Key cacheKey = null; String filterName = null; String currentFieldName = null; double lat = 0; double lon = 0; String fieldName = null; double distance = 0; Object vDistance = null; DistanceUnit unit = DistanceUnit.KILOMETERS; GeoDistance geoDistance = GeoDistance.ARC; String optimizeBbox = "memory"; boolean normalizeLon = true; boolean normalizeLat = true; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_ARRAY) { token = parser.nextToken(); lon = parser.doubleValue(); token = parser.nextToken(); lat = parser.doubleValue(); while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {} fieldName = currentFieldName; } else if (token == XContentParser.Token.START_OBJECT) { String currentName = parser.currentName(); fieldName = currentFieldName; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentName = parser.currentName(); } else if (token.isValue()) { if (currentName.equals(GeoPointFieldMapper.Names.LAT)) { lat = parser.doubleValue(); } else if (currentName.equals(GeoPointFieldMapper.Names.LON)) { lon = parser.doubleValue(); } else if (currentName.equals(GeoPointFieldMapper.Names.GEOHASH)) { double[] values = GeoHashUtils.decode(parser.text()); lat = values[0]; lon = values[1]; } else { throw new QueryParsingException( parseContext.index(), "[geo_distance] filter does not support [" + currentFieldName + "]"); } } } } else if (token.isValue()) { if (currentFieldName.equals("distance")) { if (token == XContentParser.Token.VALUE_STRING) { vDistance = parser.text(); } else { vDistance = parser.numberValue(); } } else if (currentFieldName.equals("unit")) { unit = DistanceUnit.fromString(parser.text()); } else if (currentFieldName.equals("distance_type") || currentFieldName.equals("distanceType")) { geoDistance = GeoDistance.fromString(parser.text()); } else if (currentFieldName.endsWith(GeoPointFieldMapper.Names.LAT_SUFFIX)) { lat = parser.doubleValue(); fieldName = currentFieldName.substring( 0, currentFieldName.length() - GeoPointFieldMapper.Names.LAT_SUFFIX.length()); } else if (currentFieldName.endsWith(GeoPointFieldMapper.Names.LON_SUFFIX)) { lon = parser.doubleValue(); fieldName = currentFieldName.substring( 0, currentFieldName.length() - GeoPointFieldMapper.Names.LON_SUFFIX.length()); } else if (currentFieldName.endsWith(GeoPointFieldMapper.Names.GEOHASH_SUFFIX)) { double[] values = GeoHashUtils.decode(parser.text()); lat = values[0]; lon = values[1]; fieldName = currentFieldName.substring( 0, currentFieldName.length() - GeoPointFieldMapper.Names.GEOHASH_SUFFIX.length()); } else if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else if ("_cache".equals(currentFieldName)) { cache = parser.booleanValue(); } else if ("_cache_key".equals(currentFieldName) || "_cacheKey".equals(currentFieldName)) { cacheKey = new CacheKeyFilter.Key(parser.text()); } else if ("optimize_bbox".equals(currentFieldName) || "optimizeBbox".equals(currentFieldName)) { optimizeBbox = parser.textOrNull(); } else if ("normalize".equals(currentFieldName)) { normalizeLat = parser.booleanValue(); normalizeLon = parser.booleanValue(); } else { String value = parser.text(); int comma = value.indexOf(','); if (comma != -1) { lat = Double.parseDouble(value.substring(0, comma).trim()); lon = Double.parseDouble(value.substring(comma + 1).trim()); } else { double[] values = GeoHashUtils.decode(value); lat = values[0]; lon = values[1]; } fieldName = currentFieldName; } } } if (vDistance instanceof Number) { distance = unit.toMiles(((Number) vDistance).doubleValue()); } else { distance = DistanceUnit.parse((String) vDistance, unit, DistanceUnit.MILES); } distance = geoDistance.normalize(distance, DistanceUnit.MILES); if (normalizeLat) { lat = GeoUtils.normalizeLat(lat); } if (normalizeLon) { lon = GeoUtils.normalizeLon(lon); } MapperService.SmartNameFieldMappers smartMappers = parseContext.smartFieldMappers(fieldName); if (smartMappers == null || !smartMappers.hasMapper()) { throw new QueryParsingException( parseContext.index(), "failed to find geo_point field [" + fieldName + "]"); } FieldMapper mapper = smartMappers.mapper(); if (mapper.fieldDataType() != GeoPointFieldDataType.TYPE) { throw new QueryParsingException( parseContext.index(), "field [" + fieldName + "] is not a geo_point field"); } GeoPointFieldMapper geoMapper = ((GeoPointFieldMapper.GeoStringFieldMapper) mapper).geoMapper(); fieldName = mapper.names().indexName(); Filter filter = new GeoDistanceFilter( lat, lon, distance, geoDistance, fieldName, geoMapper, parseContext.indexCache().fieldData(), optimizeBbox); if (cache) { filter = parseContext.cacheFilter(filter, cacheKey); } filter = QueryParsers.wrapSmartNameFilter(filter, smartMappers, parseContext); if (filterName != null) { parseContext.addNamedFilter(filterName, filter); } return filter; }
@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); XContentParser.Token token; boolean cache = false; CacheKeyFilter.Key cacheKey = null; String filterName = null; String currentFieldName = null; double lat = 0; double lon = 0; String fieldName = null; Object vFrom = null; Object vTo = null; boolean includeLower = true; boolean includeUpper = true; DistanceUnit unit = DistanceUnit.KILOMETERS; // default unit GeoDistance geoDistance = GeoDistance.ARC; String optimizeBbox = "memory"; boolean normalizeLon = true; boolean normalizeLat = true; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_ARRAY) { token = parser.nextToken(); lon = parser.doubleValue(); token = parser.nextToken(); lat = parser.doubleValue(); while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {} fieldName = currentFieldName; } else if (token == XContentParser.Token.START_OBJECT) { // the json in the format of -> field : { lat : 30, lon : 12 } String currentName = parser.currentName(); fieldName = currentFieldName; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentName = parser.currentName(); } else if (token.isValue()) { if (currentName.equals(GeoPointFieldMapper.Names.LAT)) { lat = parser.doubleValue(); } else if (currentName.equals(GeoPointFieldMapper.Names.LON)) { lon = parser.doubleValue(); } else if (currentName.equals(GeoPointFieldMapper.Names.GEOHASH)) { double[] values = GeoHashUtils.decode(parser.text()); lat = values[0]; lon = values[1]; } } } } else if (token.isValue()) { if (currentFieldName.equals("from")) { if (token == XContentParser.Token.VALUE_NULL) { } else if (token == XContentParser.Token.VALUE_STRING) { vFrom = parser.text(); // a String } else { vFrom = parser.numberValue(); // a Number } } else if (currentFieldName.equals("to")) { if (token == XContentParser.Token.VALUE_NULL) { } else if (token == XContentParser.Token.VALUE_STRING) { vTo = parser.text(); // a String } else { vTo = parser.numberValue(); // a Number } } else if ("include_lower".equals(currentFieldName) || "includeLower".equals(currentFieldName)) { includeLower = parser.booleanValue(); } else if ("include_upper".equals(currentFieldName) || "includeUpper".equals(currentFieldName)) { includeUpper = parser.booleanValue(); } else if ("gt".equals(currentFieldName)) { if (token == XContentParser.Token.VALUE_NULL) { } else if (token == XContentParser.Token.VALUE_STRING) { vFrom = parser.text(); // a String } else { vFrom = parser.numberValue(); // a Number } includeLower = false; } else if ("gte".equals(currentFieldName) || "ge".equals(currentFieldName)) { if (token == XContentParser.Token.VALUE_NULL) { } else if (token == XContentParser.Token.VALUE_STRING) { vFrom = parser.text(); // a String } else { vFrom = parser.numberValue(); // a Number } includeLower = true; } else if ("lt".equals(currentFieldName)) { if (token == XContentParser.Token.VALUE_NULL) { } else if (token == XContentParser.Token.VALUE_STRING) { vTo = parser.text(); // a String } else { vTo = parser.numberValue(); // a Number } includeUpper = false; } else if ("lte".equals(currentFieldName) || "le".equals(currentFieldName)) { if (token == XContentParser.Token.VALUE_NULL) { } else if (token == XContentParser.Token.VALUE_STRING) { vTo = parser.text(); // a String } else { vTo = parser.numberValue(); // a Number } includeUpper = true; } else if (currentFieldName.equals("unit")) { unit = DistanceUnit.fromString(parser.text()); } else if (currentFieldName.equals("distance_type") || currentFieldName.equals("distanceType")) { geoDistance = GeoDistance.fromString(parser.text()); } else if (currentFieldName.endsWith(GeoPointFieldMapper.Names.LAT_SUFFIX)) { lat = parser.doubleValue(); fieldName = currentFieldName.substring( 0, currentFieldName.length() - GeoPointFieldMapper.Names.LAT_SUFFIX.length()); } else if (currentFieldName.endsWith(GeoPointFieldMapper.Names.LON_SUFFIX)) { lon = parser.doubleValue(); fieldName = currentFieldName.substring( 0, currentFieldName.length() - GeoPointFieldMapper.Names.LON_SUFFIX.length()); } else if (currentFieldName.endsWith(GeoPointFieldMapper.Names.GEOHASH_SUFFIX)) { double[] values = GeoHashUtils.decode(parser.text()); lat = values[0]; lon = values[1]; fieldName = currentFieldName.substring( 0, currentFieldName.length() - GeoPointFieldMapper.Names.GEOHASH_SUFFIX.length()); } else if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else if ("_cache".equals(currentFieldName)) { cache = parser.booleanValue(); } else if ("_cache_key".equals(currentFieldName) || "_cacheKey".equals(currentFieldName)) { cacheKey = new CacheKeyFilter.Key(parser.text()); } else if ("optimize_bbox".equals(currentFieldName) || "optimizeBbox".equals(currentFieldName)) { optimizeBbox = parser.textOrNull(); } else if ("normalize".equals(currentFieldName)) { normalizeLat = parser.booleanValue(); normalizeLon = parser.booleanValue(); } else { // assume the value is the actual value String value = parser.text(); int comma = value.indexOf(','); if (comma != -1) { lat = Double.parseDouble(value.substring(0, comma).trim()); lon = Double.parseDouble(value.substring(comma + 1).trim()); } else { double[] values = GeoHashUtils.decode(value); lat = values[0]; lon = values[1]; } fieldName = currentFieldName; } } } Double from = null; Double to = null; if (vFrom != null) { if (vFrom instanceof Number) { from = unit.toMiles(((Number) vFrom).doubleValue()); } else { from = DistanceUnit.parse((String) vFrom, unit, DistanceUnit.MILES); } from = geoDistance.normalize(from, DistanceUnit.MILES); } if (vTo != null) { if (vTo instanceof Number) { to = unit.toMiles(((Number) vTo).doubleValue()); } else { to = DistanceUnit.parse((String) vTo, unit, DistanceUnit.MILES); } to = geoDistance.normalize(to, DistanceUnit.MILES); } if (normalizeLat) { lat = GeoUtils.normalizeLat(lat); } if (normalizeLon) { lon = GeoUtils.normalizeLon(lon); } MapperService.SmartNameFieldMappers smartMappers = parseContext.smartFieldMappers(fieldName); if (smartMappers == null || !smartMappers.hasMapper()) { throw new QueryParsingException( parseContext.index(), "failed to find geo_point field [" + fieldName + "]"); } FieldMapper mapper = smartMappers.mapper(); if (mapper.fieldDataType() != GeoPointFieldDataType.TYPE) { throw new QueryParsingException( parseContext.index(), "field [" + fieldName + "] is not a geo_point field"); } GeoPointFieldMapper geoMapper = ((GeoPointFieldMapper.GeoStringFieldMapper) mapper).geoMapper(); fieldName = mapper.names().indexName(); Filter filter = new GeoDistanceRangeFilter( lat, lon, from, to, includeLower, includeUpper, geoDistance, fieldName, geoMapper, parseContext.indexCache().fieldData(), optimizeBbox); if (cache) { filter = parseContext.cacheFilter(filter, cacheKey); } filter = wrapSmartNameFilter(filter, smartMappers, parseContext); if (filterName != null) { parseContext.addNamedFilter(filterName, filter); } return filter; }
@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); Query query = null; Filter filter = null; float boost = 1.0f; String scope = null; String path = null; boolean cache = false; String filterName = null; // we need a late binding filter so we can inject a parent nested filter inner nested queries NestedQueryParser.LateBindingParentFilter currentParentFilterContext = NestedQueryParser.parentFilterContext.get(); NestedQueryParser.LateBindingParentFilter usAsParentFilter = new NestedQueryParser.LateBindingParentFilter(); NestedQueryParser.parentFilterContext.set(usAsParentFilter); 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)) { query = parseContext.parseInnerQuery(); } else if ("filter".equals(currentFieldName)) { filter = parseContext.parseInnerFilter(); } } else if (token.isValue()) { if ("path".equals(currentFieldName)) { path = parser.text(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("_scope".equals(currentFieldName)) { scope = parser.text(); } else if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else if ("_cache".equals(currentFieldName)) { cache = parser.booleanValue(); } } } if (query == null && filter == null) { throw new QueryParsingException( parseContext.index(), "[nested] requires either 'query' or 'filter' field"); } if (path == null) { throw new QueryParsingException(parseContext.index(), "[nested] requires 'path' field"); } if (filter != null) { query = new DeletionAwareConstantScoreQuery(filter); } query.setBoost(boost); MapperService.SmartNameObjectMapper mapper = parseContext.mapperService().smartNameObjectMapper(path); if (mapper == null) { throw new QueryParsingException( parseContext.index(), "[nested] failed to find nested object under path [" + path + "]"); } ObjectMapper objectMapper = mapper.mapper(); if (objectMapper == null) { throw new QueryParsingException( parseContext.index(), "[nested] failed to find nested object under path [" + path + "]"); } if (!objectMapper.nested().isNested()) { throw new QueryParsingException( parseContext.index(), "[nested] nested object under path [" + path + "] is not of nested type"); } Filter childFilter = parseContext.cacheFilter(objectMapper.nestedTypeFilter()); usAsParentFilter.filter = childFilter; // wrap the child query to only work on the nested path type query = new FilteredQuery(query, childFilter); Filter parentFilter = currentParentFilterContext; if (parentFilter == null) { parentFilter = NonNestedDocsFilter.INSTANCE; if (mapper.hasDocMapper()) { // filter based on the type... parentFilter = mapper.docMapper().typeFilter(); } parentFilter = parseContext.cacheFilter(parentFilter); } // restore the thread local one... NestedQueryParser.parentFilterContext.set(currentParentFilterContext); BlockJoinQuery joinQuery = new BlockJoinQuery(query, parentFilter, BlockJoinQuery.ScoreMode.None); if (scope != null) { SearchContext.current().addNestedQuery(scope, joinQuery); } Filter joinFilter = new QueryWrapperFilter(joinQuery); if (cache) { joinFilter = parseContext.cacheFilter(joinFilter); } if (filterName != null) { parseContext.addNamedFilter(filterName, joinFilter); } return joinFilter; }
@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 Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); String fieldName = null; ShapeRelation shapeRelation = ShapeRelation.INTERSECTS; String strategyName = null; ShapeBuilder shape = null; FilterCachingPolicy cache = parseContext.autoFilterCachePolicy(); HashedBytesRef cacheKey = null; String filterName = null; String id = null; String type = null; String index = DEFAULTS.INDEX_NAME; String shapePath = DEFAULTS.SHAPE_FIELD_NAME; XContentParser.Token token; String currentFieldName = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { fieldName = currentFieldName; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); token = parser.nextToken(); if ("shape".equals(currentFieldName)) { shape = ShapeBuilder.parse(parser); } else if ("relation".equals(currentFieldName)) { shapeRelation = ShapeRelation.getRelationByName(parser.text()); if (shapeRelation == null) { throw new QueryParsingException( parseContext.index(), "Unknown shape operation [" + parser.text() + "]"); } } else if ("strategy".equals(currentFieldName)) { strategyName = parser.text(); } else if ("indexed_shape".equals(currentFieldName) || "indexedShape".equals(currentFieldName)) { while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token.isValue()) { if ("id".equals(currentFieldName)) { id = parser.text(); } else if ("type".equals(currentFieldName)) { type = parser.text(); } else if ("index".equals(currentFieldName)) { index = parser.text(); } else if ("path".equals(currentFieldName)) { shapePath = parser.text(); } } } if (id == null) { throw new QueryParsingException( parseContext.index(), "ID for indexed shape not provided"); } else if (type == null) { throw new QueryParsingException( parseContext.index(), "Type for indexed shape not provided"); } shape = fetchService.fetch(id, type, index, shapePath); } else { throw new QueryParsingException( parseContext.index(), "[geo_shape] filter does not support [" + currentFieldName + "]"); } } } } else if (token.isValue()) { if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else if ("_cache".equals(currentFieldName)) { cache = parseContext.parseFilterCachePolicy(); } else if ("_cache_key".equals(currentFieldName)) { cacheKey = new HashedBytesRef(parser.text()); } else { throw new QueryParsingException( parseContext.index(), "[geo_shape] filter does not support [" + currentFieldName + "]"); } } } if (shape == null) { throw new QueryParsingException(parseContext.index(), "No Shape defined"); } else if (shapeRelation == null) { throw new QueryParsingException(parseContext.index(), "No Shape Relation defined"); } MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); if (smartNameFieldMappers == null || !smartNameFieldMappers.hasMapper()) { throw new QueryParsingException( parseContext.index(), "Failed to find geo_shape field [" + fieldName + "]"); } FieldMapper fieldMapper = smartNameFieldMappers.mapper(); // TODO: This isn't the nicest way to check this if (!(fieldMapper instanceof GeoShapeFieldMapper)) { throw new QueryParsingException( parseContext.index(), "Field [" + fieldName + "] is not a geo_shape"); } GeoShapeFieldMapper shapeFieldMapper = (GeoShapeFieldMapper) fieldMapper; PrefixTreeStrategy strategy = shapeFieldMapper.defaultStrategy(); if (strategyName != null) { strategy = shapeFieldMapper.resolveStrategy(strategyName); } Filter filter; if (strategy instanceof RecursivePrefixTreeStrategy && shapeRelation == ShapeRelation.DISJOINT) { // this strategy doesn't support disjoint anymore: but it did before, including creating // lucene fieldcache (!) // in this case, execute disjoint as exists && !intersects XBooleanFilter bool = new XBooleanFilter(); Filter exists = ExistsFilterParser.newFilter(parseContext, fieldName, null); Filter intersects = strategy.makeFilter(GeoShapeQueryParser.getArgs(shape, ShapeRelation.INTERSECTS)); bool.add(exists, BooleanClause.Occur.MUST); bool.add(intersects, BooleanClause.Occur.MUST_NOT); filter = bool; } else { filter = strategy.makeFilter(GeoShapeQueryParser.getArgs(shape, shapeRelation)); } if (cache != null) { filter = parseContext.cacheFilter(filter, cacheKey, cache); } if (filterName != null) { parseContext.addNamedFilter(filterName, filter); } return filter; }
@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); XContentParser.Token token; boolean cache = false; // no need to cache it by default, changes a lot? CacheKeyFilter.Key cacheKey = null; // also, when caching, since its isCacheable is false, will result in loading all bit set... String script = null; String scriptLang = null; Map<String, Object> params = null; String filterName = null; String currentFieldName = null; 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 ("params".equals(currentFieldName)) { params = parser.map(); } else { throw new QueryParsingException( parseContext.index(), "[script] filter does not support [" + currentFieldName + "]"); } } else if (token.isValue()) { if ("script".equals(currentFieldName)) { script = parser.text(); } else if ("lang".equals(currentFieldName)) { scriptLang = parser.text(); } else if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else if ("_cache".equals(currentFieldName)) { cache = parser.booleanValue(); } else if ("_cache_key".equals(currentFieldName) || "_cacheKey".equals(currentFieldName)) { cacheKey = new CacheKeyFilter.Key(parser.text()); } else { throw new QueryParsingException( parseContext.index(), "[script] filter does not support [" + currentFieldName + "]"); } } } if (script == null) { throw new QueryParsingException( parseContext.index(), "script must be provided with a [script] filter"); } if (params == null) { params = newHashMap(); } Filter filter = new ScriptFilter( scriptLang, script, params, parseContext.scriptService(), parseContext.lookup()); if (cache) { filter = parseContext.cacheFilter(filter, cacheKey); } if (filterName != null) { parseContext.addNamedFilter(filterName, filter); } return filter; }
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); boolean queryFound = false; float boost = 1.0f; String parentType = null; boolean score = false; String queryName = null; String currentFieldName = null; XContentParser.Token token; XContentStructure.InnerQuery iq = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token == XContentParser.Token.START_OBJECT) { // Usually, the query would be parsed here, but the child // type may not have been extracted yet, so use the // XContentStructure.<type> facade to parse if available, // or delay parsing if not. if ("query".equals(currentFieldName)) { iq = new XContentStructure.InnerQuery( parseContext, parentType == null ? null : new String[] {parentType}); queryFound = true; } else { throw new QueryParsingException( parseContext.index(), "[has_parent] query 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] query has been removed, use a filter as a facet_filter in the relevant global facet"); } else if ("score_type".equals(currentFieldName) || "scoreType".equals(currentFieldName)) { String scoreTypeValue = parser.text(); if ("score".equals(scoreTypeValue)) { score = true; } else if ("none".equals(scoreTypeValue)) { score = false; } } else if ("score_mode".equals(currentFieldName) || "scoreMode".equals(currentFieldName)) { String scoreModeValue = parser.text(); if ("score".equals(scoreModeValue)) { score = true; } else if ("none".equals(scoreModeValue)) { score = false; } } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("_name".equals(currentFieldName)) { queryName = parser.text(); } else { throw new QueryParsingException( parseContext.index(), "[has_parent] query does not support [" + currentFieldName + "]"); } } } if (!queryFound) { throw new QueryParsingException( parseContext.index(), "[has_parent] query requires 'query' field"); } if (parentType == null) { throw new QueryParsingException( parseContext.index(), "[has_parent] query requires 'parent_type' field"); } Query innerQuery = iq.asQuery(parentType); if (innerQuery == null) { return null; } DocumentMapper parentDocMapper = parseContext.mapperService().documentMapper(parentType); if (parentDocMapper == null) { throw new QueryParsingException( parseContext.index(), "[has_parent] query configured 'parent_type' [" + parentType + "] is not a valid type"); } innerQuery.setBoost(boost); // wrap the query with type query innerQuery = new XFilteredQuery( innerQuery, parseContext.cacheFilter(parentDocMapper.typeFilter(), null)); ParentChildIndexFieldData parentChildIndexFieldData = null; Set<String> parentTypes = new HashSet<>(5); parentTypes.add(parentType); for (DocumentMapper documentMapper : parseContext.mapperService()) { ParentFieldMapper parentFieldMapper = documentMapper.parentFieldMapper(); if (parentFieldMapper.active()) { parentChildIndexFieldData = parseContext.fieldData().getForField(parentFieldMapper); DocumentMapper parentTypeDocumentMapper = parseContext.mapperService().documentMapper(parentFieldMapper.type()); if (parentTypeDocumentMapper == null) { // Only add this, if this parentFieldMapper (also a parent) isn't a child of another // parent. parentTypes.add(parentFieldMapper.type()); } } } if (parentChildIndexFieldData == null) { throw new QueryParsingException( parseContext.index(), "[has_parent] no _parent field configured"); } Filter parentFilter; if (parentTypes.size() == 1) { DocumentMapper documentMapper = parseContext.mapperService().documentMapper(parentTypes.iterator().next()); parentFilter = parseContext.cacheFilter(documentMapper.typeFilter(), null); } else { XBooleanFilter parentsFilter = new XBooleanFilter(); for (String parentTypeStr : parentTypes) { DocumentMapper documentMapper = parseContext.mapperService().documentMapper(parentTypeStr); Filter filter = parseContext.cacheFilter(documentMapper.typeFilter(), null); parentsFilter.add(filter, BooleanClause.Occur.SHOULD); } parentFilter = parentsFilter; } Filter childrenFilter = parseContext.cacheFilter(new NotFilter(parentFilter), null); boolean deleteByQuery = "delete_by_query".equals(SearchContext.current().source()); Query query; if (!deleteByQuery && score) { query = new ParentQuery(parentChildIndexFieldData, innerQuery, parentType, childrenFilter); } else { query = new ParentConstantScoreQuery( parentChildIndexFieldData, innerQuery, parentType, childrenFilter); if (deleteByQuery) { query = new XConstantScoreQuery(new DeleteByQueryWrappingFilter(query)); } } query.setBoost(boost); if (queryName != null) { parseContext.addNamedFilter(queryName, new CustomQueryWrappingFilter(query)); } return query; }