@Override public Query apply(Function parent, Function inner, Context context) throws IOException { FunctionLiteralPair outerPair = new FunctionLiteralPair(parent); if (!outerPair.isValid()) { return null; } Query query = getQuery(inner, context); if (query == null) return null; Boolean negate = !(Boolean) outerPair.input().value(); if (negate) { BooleanQuery booleanQuery = new BooleanQuery(); booleanQuery.add(query, BooleanClause.Occur.MUST_NOT); return booleanQuery; } else { return query; } }
/** * @param parent the outer function. E.g. in the case of * <pre>where distance(p1, POINT (10 20)) > 20</pre> * this would be * <pre>gt( \<inner function\>, 20)</pre> * * @param inner has to be the distance function */ @Override public Query apply(Function parent, Function inner, Context context) { assert inner.info().ident().name().equals(DistanceFunction.NAME); RefLiteralPair distanceRefLiteral = new RefLiteralPair(inner); if (!distanceRefLiteral.isValid()) { // can't use distance filter without literal, fallback to genericFunction return null; } FunctionLiteralPair functionLiteralPair = new FunctionLiteralPair(parent); if (!functionLiteralPair.isValid()) { // must be something like eq(distance(..), non-literal) - fallback to genericFunction return null; } Double distance = DataTypes.DOUBLE.value(functionLiteralPair.input().value()); String fieldName = distanceRefLiteral.reference().info().ident().columnIdent().fqn(); FieldMapper mapper = getGeoPointFieldMapper(fieldName, context.mapperService); GeoPointFieldMapper geoMapper = ((GeoPointFieldMapper) mapper); IndexGeoPointFieldData fieldData = context.fieldDataService.getForField(mapper); Input geoPointInput = distanceRefLiteral.input(); Double[] pointValue = (Double[]) geoPointInput.value(); double lat = pointValue[1]; double lon = pointValue[0]; String parentName = functionLiteralPair.functionName(); Double from = null; Double to = null; boolean includeLower = false; boolean includeUpper = false; switch (parentName) { case EqOperator.NAME: includeLower = true; includeUpper = true; from = distance; to = distance; break; case LteOperator.NAME: includeUpper = true; to = distance; break; case LtOperator.NAME: to = distance; break; case GteOperator.NAME: from = distance; includeLower = true; break; case GtOperator.NAME: from = distance; break; default: // invalid operator? give up return null; } GeoPoint geoPoint = new GeoPoint(lat, lon); Filter filter = new GeoDistanceRangeFilter( geoPoint, from, to, includeLower, includeUpper, GEO_DISTANCE, geoMapper, fieldData, optimizeBox); return new FilteredQuery( Queries.newMatchAllQuery(), context.indexCache.filter().cache(filter)); }