@Override public Filter parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); String fieldPattern = null; String filterName = null; 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)) { fieldPattern = parser.text(); } else if ("_name".equals(currentFieldName)) { filterName = parser.text(); } else { throw new QueryParsingException( parseContext.index(), "[exists] filter does not support [" + currentFieldName + "]"); } } } if (fieldPattern == null) { throw new QueryParsingException( parseContext.index(), "exists must be provided with a [field]"); } return newFilter(parseContext, fieldPattern, filterName); }
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); Query query = null; float boost = 1.0f; String script = null; String scriptLang = null; Map<String, Object> vars = 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)) { query = parseContext.parseInnerQuery(); } else if ("params".equals(currentFieldName)) { vars = parser.map(); } } else if (token.isValue()) { if ("script".equals(currentFieldName)) { script = parser.text(); } else if ("lang".equals(currentFieldName)) { scriptLang = parser.text(); } else if ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } } } if (query == null) { throw new QueryParsingException( parseContext.index(), "[custom_score] requires 'query' field"); } if (script == null) { throw new QueryParsingException( parseContext.index(), "[custom_score] requires 'script' field"); } SearchContext context = SearchContext.current(); if (context == null) { throw new ElasticSearchIllegalStateException("No search context on going..."); } SearchScript searchScript = context.scriptService().search(context.lookup(), scriptLang, script, vars); FunctionScoreQuery functionScoreQuery = new FunctionScoreQuery(query, new ScriptScoreFunction(script, vars, searchScript)); functionScoreQuery.setBoost(boost); return functionScoreQuery; }
@Override @Nullable public Query parse(QueryParseContext parseContext) throws IOException { XContentParser parser = parseContext.parser(); TemplateContext templateContext = parse(parser, QUERY, PARAMS); ExecutableScript executable = this.scriptService.executable( "mustache", templateContext.template(), templateContext.params()); BytesReference querySource = (BytesReference) executable.run(); XContentParser qSourceParser = XContentFactory.xContent(querySource).createParser(querySource); try { final QueryParseContext context = new QueryParseContext(parseContext.index(), parseContext.indexQueryParser); context.reset(qSourceParser); Query result = context.parseInnerQuery(); parser.nextToken(); return result; } finally { qSourceParser.close(); } }
@Override public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); XContentParser.Token token = parser.nextToken(); if (token != XContentParser.Token.FIELD_NAME) { throw new QueryParsingException( parseContext.index(), "[range] query malformed, no field to indicate field name"); } String fieldName = parser.currentName(); token = parser.nextToken(); if (token != XContentParser.Token.START_OBJECT) { throw new QueryParsingException( parseContext.index(), "[range] query malformed, after field missing start object"); } BytesRef from = null; BytesRef to = null; boolean includeLower = true; boolean includeUpper = true; float boost = 1.0f; String currentFieldName = null; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else { if ("from".equals(currentFieldName)) { from = parser.bytesOrNull(); } else if ("to".equals(currentFieldName)) { to = parser.bytesOrNull(); } 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 ("boost".equals(currentFieldName)) { boost = parser.floatValue(); } else if ("gt".equals(currentFieldName)) { from = parser.bytesOrNull(); includeLower = false; } else if ("gte".equals(currentFieldName) || "ge".equals(currentFieldName)) { from = parser.bytesOrNull(); includeLower = true; } else if ("lt".equals(currentFieldName)) { to = parser.bytesOrNull(); includeUpper = false; } else if ("lte".equals(currentFieldName) || "le".equals(currentFieldName)) { to = parser.bytesOrNull(); includeUpper = true; } else { throw new QueryParsingException( parseContext.index(), "[range] query does not support [" + currentFieldName + "]"); } } } // move to the next end object, to close the field name token = parser.nextToken(); if (token != XContentParser.Token.END_OBJECT) { throw new QueryParsingException( parseContext.index(), "[range] query malformed, does not end with an object"); } Query query = null; MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName); if (smartNameFieldMappers != null) { if (smartNameFieldMappers.hasMapper()) { // LUCENE 4 UPGRADE Mapper#rangeQuery should use bytesref as well? query = smartNameFieldMappers .mapper() .rangeQuery( from != null ? from.utf8ToString() : null, to != null ? to.utf8ToString() : null, includeLower, includeUpper, parseContext); } } if (query == null) { query = new TermRangeQuery(fieldName, from, to, includeLower, includeUpper); } query.setBoost(boost); return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext); }
@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 Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException { XContentParser parser = parseContext.parser(); MoreLikeThisQuery mltQuery = new MoreLikeThisQuery(); mltQuery.setSimilarity(parseContext.searchSimilarity()); Analyzer analyzer = null; List<String> moreLikeFields = null; boolean failOnUnsupportedField = true; String queryName = null; boolean include = false; XContentParser.Token token; String currentFieldName = null; List<String> likeTexts = new ArrayList<>(); MultiTermVectorsRequest likeItems = new MultiTermVectorsRequest(); List<String> unlikeTexts = new ArrayList<>(); MultiTermVectorsRequest unlikeItems = new MultiTermVectorsRequest(); while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); } else if (token.isValue()) { if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.LIKE_TEXT)) { likeTexts.add(parser.text()); } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.LIKE)) { parseLikeField(parser, likeTexts, likeItems); } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.UNLIKE)) { parseLikeField(parser, unlikeTexts, unlikeItems); } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.MIN_TERM_FREQ)) { mltQuery.setMinTermFrequency(parser.intValue()); } else if (parseContext .parseFieldMatcher() .match(currentFieldName, Fields.MAX_QUERY_TERMS)) { mltQuery.setMaxQueryTerms(parser.intValue()); } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.MIN_DOC_FREQ)) { mltQuery.setMinDocFreq(parser.intValue()); } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.MAX_DOC_FREQ)) { mltQuery.setMaxDocFreq(parser.intValue()); } else if (parseContext .parseFieldMatcher() .match(currentFieldName, Fields.MIN_WORD_LENGTH)) { mltQuery.setMinWordLen(parser.intValue()); } else if (parseContext .parseFieldMatcher() .match(currentFieldName, Fields.MAX_WORD_LENGTH)) { mltQuery.setMaxWordLen(parser.intValue()); } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.BOOST_TERMS)) { float boostFactor = parser.floatValue(); if (boostFactor != 0) { mltQuery.setBoostTerms(true); mltQuery.setBoostTermsFactor(boostFactor); } } else if (parseContext .parseFieldMatcher() .match(currentFieldName, Fields.MINIMUM_SHOULD_MATCH)) { mltQuery.setMinimumShouldMatch(parser.text()); } else if ("analyzer".equals(currentFieldName)) { analyzer = parseContext.analysisService().analyzer(parser.text()); } else if ("boost".equals(currentFieldName)) { mltQuery.setBoost(parser.floatValue()); } else if (parseContext .parseFieldMatcher() .match(currentFieldName, Fields.FAIL_ON_UNSUPPORTED_FIELD)) { failOnUnsupportedField = parser.booleanValue(); } else if ("_name".equals(currentFieldName)) { queryName = parser.text(); } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.INCLUDE)) { include = parser.booleanValue(); } else { throw new QueryParsingException( parseContext, "[mlt] query does not support [" + currentFieldName + "]"); } } else if (token == XContentParser.Token.START_ARRAY) { if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.STOP_WORDS)) { Set<String> stopWords = Sets.newHashSet(); while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { stopWords.add(parser.text()); } mltQuery.setStopWords(stopWords); } else if ("fields".equals(currentFieldName)) { moreLikeFields = new LinkedList<>(); while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { String field = parser.text(); MappedFieldType fieldType = parseContext.fieldMapper(field); moreLikeFields.add(fieldType == null ? field : fieldType.names().indexName()); } } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.DOCUMENT_IDS)) { while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { if (!token.isValue()) { throw new IllegalArgumentException("ids array element should only contain ids"); } likeItems.add(newTermVectorsRequest().id(parser.text())); } } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.DOCUMENTS)) { while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { if (token != XContentParser.Token.START_OBJECT) { throw new IllegalArgumentException("docs array element should include an object"); } likeItems.add(parseDocument(parser)); } } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.LIKE)) { while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { parseLikeField(parser, likeTexts, likeItems); } } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.UNLIKE)) { while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) { parseLikeField(parser, unlikeTexts, unlikeItems); } } else { throw new QueryParsingException( parseContext, "[mlt] query does not support [" + currentFieldName + "]"); } } else if (token == XContentParser.Token.START_OBJECT) { if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.LIKE)) { parseLikeField(parser, likeTexts, likeItems); } else if (parseContext.parseFieldMatcher().match(currentFieldName, Fields.UNLIKE)) { parseLikeField(parser, unlikeTexts, unlikeItems); } else { throw new QueryParsingException( parseContext, "[mlt] query does not support [" + currentFieldName + "]"); } } } if (likeTexts.isEmpty() && likeItems.isEmpty()) { throw new QueryParsingException( parseContext, "more_like_this requires 'like' to be specified"); } if (moreLikeFields != null && moreLikeFields.isEmpty()) { throw new QueryParsingException( parseContext, "more_like_this requires 'fields' to be non-empty"); } // set analyzer if (analyzer == null) { analyzer = parseContext.mapperService().searchAnalyzer(); } mltQuery.setAnalyzer(analyzer); // set like text fields boolean useDefaultField = (moreLikeFields == null); if (useDefaultField) { moreLikeFields = Collections.singletonList(parseContext.defaultField()); } // possibly remove unsupported fields removeUnsupportedFields(moreLikeFields, analyzer, failOnUnsupportedField); if (moreLikeFields.isEmpty()) { return null; } mltQuery.setMoreLikeFields(moreLikeFields.toArray(Strings.EMPTY_ARRAY)); // support for named query if (queryName != null) { parseContext.addNamedQuery(queryName, mltQuery); } // handle like texts if (!likeTexts.isEmpty()) { mltQuery.setLikeText(likeTexts); } if (!unlikeTexts.isEmpty()) { mltQuery.setIgnoreText(unlikeTexts); } // handle items if (!likeItems.isEmpty()) { // set default index, type and fields if not specified MultiTermVectorsRequest items = likeItems; for (TermVectorsRequest item : unlikeItems) { items.add(item); } for (TermVectorsRequest item : items) { if (item.index() == null) { item.index(parseContext.index().name()); } if (item.type() == null) { if (parseContext.queryTypes().size() > 1) { throw new QueryParsingException( parseContext, "ambiguous type for item with id: " + item.id() + " and index: " + item.index()); } else { item.type(parseContext.queryTypes().iterator().next()); } } // default fields if not present but don't override for artificial docs if (item.selectedFields() == null && item.doc() == null) { if (useDefaultField) { item.selectedFields("*"); } else { item.selectedFields(moreLikeFields.toArray(new String[moreLikeFields.size()])); } } } // fetching the items with multi-termvectors API items.copyContextAndHeadersFrom(SearchContext.current()); MultiTermVectorsResponse responses = fetchService.fetchResponse(items); // getting the Fields for liked items mltQuery.setLikeText(MoreLikeThisFetchService.getFields(responses, likeItems)); // getting the Fields for ignored items if (!unlikeItems.isEmpty()) { org.apache.lucene.index.Fields[] ignoreFields = MoreLikeThisFetchService.getFields(responses, unlikeItems); if (ignoreFields.length > 0) { mltQuery.setUnlikeText(ignoreFields); } } BooleanQuery.Builder boolQuery = new BooleanQuery.Builder(); boolQuery.add(mltQuery, BooleanClause.Occur.SHOULD); // exclude the items from the search if (!include) { handleExclude(boolQuery, likeItems); } return boolQuery.build(); } return mltQuery; }
@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 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 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(); Query query = null; Query noMatchQuery = Queries.newMatchAllQuery(); boolean queryFound = false; boolean indicesFound = false; boolean currentIndexMatchesIndices = false; String queryName = 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 We are able to decide whether to parse the query or not only if indices in the // query appears first queryFound = true; if (indicesFound && !currentIndexMatchesIndices) { parseContext.parser().skipChildren(); // skip the query object without parsing it } else { query = parseContext.parseInnerQuery(); } } else if ("no_match_query".equals(currentFieldName)) { if (indicesFound && currentIndexMatchesIndices) { parseContext.parser().skipChildren(); // skip the query object without parsing it } else { noMatchQuery = parseContext.parseInnerQuery(); } } else { throw new QueryParsingException( parseContext.index(), "[indices] query does not support [" + currentFieldName + "]"); } } else if (token == XContentParser.Token.START_ARRAY) { if ("indices".equals(currentFieldName)) { if (indicesFound) { throw new QueryParsingException( parseContext.index(), "[indices] indices or index already specified"); } indicesFound = true; Collection<String> indices = new ArrayList<>(); while (parser.nextToken() != XContentParser.Token.END_ARRAY) { String value = parser.textOrNull(); if (value == null) { throw new QueryParsingException( parseContext.index(), "[indices] no value specified for 'indices' entry"); } indices.add(value); } currentIndexMatchesIndices = matchesIndices( parseContext.index().name(), indices.toArray(new String[indices.size()])); } else { throw new QueryParsingException( parseContext.index(), "[indices] query does not support [" + currentFieldName + "]"); } } else if (token.isValue()) { if ("index".equals(currentFieldName)) { if (indicesFound) { throw new QueryParsingException( parseContext.index(), "[indices] indices or index already specified"); } indicesFound = true; currentIndexMatchesIndices = matchesIndices(parseContext.index().name(), parser.text()); } else if ("no_match_query".equals(currentFieldName)) { String type = parser.text(); if ("all".equals(type)) { noMatchQuery = Queries.newMatchAllQuery(); } else if ("none".equals(type)) { noMatchQuery = Queries.newMatchNoDocsQuery(); } } else if ("_name".equals(currentFieldName)) { queryName = parser.text(); } else { throw new QueryParsingException( parseContext.index(), "[indices] query does not support [" + currentFieldName + "]"); } } } if (!queryFound) { throw new QueryParsingException(parseContext.index(), "[indices] requires 'query' element"); } if (!indicesFound) { throw new QueryParsingException( parseContext.index(), "[indices] requires 'indices' or 'index' element"); } Query chosenQuery; if (currentIndexMatchesIndices) { chosenQuery = query; } else { chosenQuery = noMatchQuery; } if (queryName != null) { parseContext.addNamedQuery(queryName, chosenQuery); } return chosenQuery; }
@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(); 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); } } }
@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 { 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(); 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(); 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 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; }