Search in sources :

Example 6 with SpatialOperation

use of org.apache.lucene.spatial.query.SpatialOperation in project lucene-solr by apache.

the class BBoxStrategy method makeQuery.

//---------------------------------
// Query Building
//---------------------------------
//  Utility on SpatialStrategy?
//  public Query makeQueryWithValueSource(SpatialArgs args, ValueSource valueSource) {
//    return new CustomScoreQuery(makeQuery(args), new FunctionQuery(valueSource));
//or...
//  return new BooleanQuery.Builder()
//      .add(new FunctionQuery(valueSource), BooleanClause.Occur.MUST)//matches everything and provides score
//      .add(filterQuery, BooleanClause.Occur.FILTER)//filters (score isn't used)
//  .build();
//  }
@Override
public Query makeQuery(SpatialArgs args) {
    Shape shape = args.getShape();
    if (!(shape instanceof Rectangle))
        throw new UnsupportedOperationException("Can only query by Rectangle, not " + shape);
    Rectangle bbox = (Rectangle) shape;
    Query spatial;
    // Useful for understanding Relations:
    // http://edndoc.esri.com/arcsde/9.1/general_topics/understand_spatial_relations.htm
    SpatialOperation op = args.getOperation();
    if (op == SpatialOperation.BBoxIntersects)
        spatial = makeIntersects(bbox);
    else if (op == SpatialOperation.BBoxWithin)
        spatial = makeWithin(bbox);
    else if (op == SpatialOperation.Contains)
        spatial = makeContains(bbox);
    else if (op == SpatialOperation.Intersects)
        spatial = makeIntersects(bbox);
    else if (op == SpatialOperation.IsEqualTo)
        spatial = makeEquals(bbox);
    else if (op == SpatialOperation.IsDisjointTo)
        spatial = makeDisjoint(bbox);
    else if (op == SpatialOperation.IsWithin)
        spatial = makeWithin(bbox);
    else {
        //no Overlaps support yet
        throw new UnsupportedSpatialOperation(op);
    }
    return new ConstantScoreQuery(spatial);
}
Also used : UnsupportedSpatialOperation(org.apache.lucene.spatial.query.UnsupportedSpatialOperation) Shape(org.locationtech.spatial4j.shape.Shape) Query(org.apache.lucene.search.Query) TermQuery(org.apache.lucene.search.TermQuery) BooleanQuery(org.apache.lucene.search.BooleanQuery) ConstantScoreQuery(org.apache.lucene.search.ConstantScoreQuery) Rectangle(org.locationtech.spatial4j.shape.Rectangle) ConstantScoreQuery(org.apache.lucene.search.ConstantScoreQuery) UnsupportedSpatialOperation(org.apache.lucene.spatial.query.UnsupportedSpatialOperation) SpatialOperation(org.apache.lucene.spatial.query.SpatialOperation)

Example 7 with SpatialOperation

use of org.apache.lucene.spatial.query.SpatialOperation in project lucene-solr by apache.

the class CompositeSpatialStrategy method makeQuery.

@Override
public Query makeQuery(SpatialArgs args) {
    final SpatialOperation pred = args.getOperation();
    if (pred == SpatialOperation.BBoxIntersects || pred == SpatialOperation.BBoxWithin) {
        throw new UnsupportedSpatialOperation(pred);
    }
    if (pred == SpatialOperation.IsDisjointTo) {
        // update class docs when it's added.
        throw new UnsupportedSpatialOperation(pred);
    }
    final ShapePredicateValueSource predicateValueSource = new ShapePredicateValueSource(geometryStrategy.makeShapeValueSource(), pred, args.getShape());
    //System.out.println("PredOpt: " + optimizePredicates);
    if (pred == SpatialOperation.Intersects && optimizePredicates) {
        // We have a smart Intersects impl
        final SpatialPrefixTree grid = indexStrategy.getGrid();
        //default to max precision
        final int detailLevel = grid.getLevelForDistance(args.resolveDistErr(ctx, 0.0));
        return new IntersectsRPTVerifyQuery(args.getShape(), indexStrategy.getFieldName(), grid, detailLevel, indexStrategy.getPrefixGridScanLevel(), predicateValueSource);
    } else {
        //The general path; all index matches get verified
        SpatialArgs indexArgs;
        if (pred == SpatialOperation.Contains) {
            // note: we could map IsWithin as well but it's pretty darned slow since it touches all world grids
            indexArgs = args;
        } else {
            //TODO add args.clone method with new predicate? Or simply make non-final?
            indexArgs = new SpatialArgs(SpatialOperation.Intersects, args.getShape());
            indexArgs.setDistErr(args.getDistErr());
            indexArgs.setDistErrPct(args.getDistErrPct());
        }
        if (indexArgs.getDistErr() == null && indexArgs.getDistErrPct() == null) {
            indexArgs.setDistErrPct(0.10);
        }
        final Query indexQuery = indexStrategy.makeQuery(indexArgs);
        return new CompositeVerifyQuery(indexQuery, predicateValueSource);
    }
}
Also used : UnsupportedSpatialOperation(org.apache.lucene.spatial.query.UnsupportedSpatialOperation) SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) Query(org.apache.lucene.search.Query) ShapePredicateValueSource(org.apache.lucene.spatial.util.ShapePredicateValueSource) SpatialPrefixTree(org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree) UnsupportedSpatialOperation(org.apache.lucene.spatial.query.UnsupportedSpatialOperation) SpatialOperation(org.apache.lucene.spatial.query.SpatialOperation) Point(org.locationtech.spatial4j.shape.Point)

Example 8 with SpatialOperation

use of org.apache.lucene.spatial.query.SpatialOperation in project lucene-solr by apache.

the class DateRangeField method parseSpatialArgs.

@Override
protected SpatialArgs parseSpatialArgs(QParser parser, String externalVal) {
    //We avoid SpatialArgsParser entirely because it isn't very Solr-friendly
    final Shape shape = parseShape(externalVal);
    final SolrParams localParams = parser.getLocalParams();
    SpatialOperation op = SpatialOperation.Intersects;
    if (localParams != null) {
        String opStr = localParams.get(OP_PARAM);
        if (opStr != null)
            op = SpatialOperation.get(opStr);
    }
    return new SpatialArgs(op, shape);
}
Also used : SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) NRShape(org.apache.lucene.spatial.prefix.tree.NumberRangePrefixTree.NRShape) Shape(org.locationtech.spatial4j.shape.Shape) UnitNRShape(org.apache.lucene.spatial.prefix.tree.NumberRangePrefixTree.UnitNRShape) SolrParams(org.apache.solr.common.params.SolrParams) SpatialOperation(org.apache.lucene.spatial.query.SpatialOperation)

Example 9 with SpatialOperation

use of org.apache.lucene.spatial.query.SpatialOperation in project janusgraph by JanusGraph.

the class LuceneIndex method convertQuery.

private SearchParams convertQuery(Condition<?> condition, final KeyInformation.StoreRetriever information, final LuceneCustomAnalyzer delegatingAnalyzer) {
    final SearchParams params = new SearchParams();
    if (condition instanceof PredicateCondition) {
        final PredicateCondition<String, ?> atom = (PredicateCondition) condition;
        Object value = atom.getValue();
        final String key = atom.getKey();
        final JanusGraphPredicate janusgraphPredicate = atom.getPredicate();
        if (value instanceof Number) {
            Preconditions.checkArgument(janusgraphPredicate instanceof Cmp, "Relation not supported on numeric types: " + janusgraphPredicate);
            params.addQuery(numericQuery(key, (Cmp) janusgraphPredicate, (Number) value));
        } else if (value instanceof String) {
            if (janusgraphPredicate == Cmp.LESS_THAN) {
                params.addQuery(TermRangeQuery.newStringRange(key, null, value.toString(), false, false));
            } else if (janusgraphPredicate == Cmp.LESS_THAN_EQUAL) {
                params.addQuery(TermRangeQuery.newStringRange(key, null, value.toString(), false, true));
            } else if (janusgraphPredicate == Cmp.GREATER_THAN) {
                params.addQuery(TermRangeQuery.newStringRange(key, value.toString(), null, false, false));
            } else if (janusgraphPredicate == Cmp.GREATER_THAN_EQUAL) {
                params.addQuery(TermRangeQuery.newStringRange(key, value.toString(), null, true, false));
            } else {
                final Mapping map = Mapping.getMapping(information.get(key));
                if ((map == Mapping.DEFAULT || map == Mapping.TEXT) && !Text.HAS_CONTAINS.contains(janusgraphPredicate))
                    throw new IllegalArgumentException("Text mapped string values only support CONTAINS queries and not: " + janusgraphPredicate);
                if (map == Mapping.STRING && Text.HAS_CONTAINS.contains(janusgraphPredicate))
                    throw new IllegalArgumentException("String mapped string values do not support CONTAINS queries: " + janusgraphPredicate);
                if (janusgraphPredicate == Text.CONTAINS) {
                    tokenize(params, map, delegatingAnalyzer, ((String) value).toLowerCase(), key, janusgraphPredicate);
                } else if (janusgraphPredicate == Text.CONTAINS_PREFIX) {
                    tokenize(params, map, delegatingAnalyzer, (String) value, key, janusgraphPredicate);
                } else if (janusgraphPredicate == Text.PREFIX) {
                    params.addQuery(new PrefixQuery(new Term(key, (String) value)));
                } else if (janusgraphPredicate == Text.REGEX) {
                    final RegexpQuery rq = new RegexpQuery(new Term(key, (String) value));
                    params.addQuery(rq);
                } else if (janusgraphPredicate == Text.CONTAINS_REGEX) {
                    // This is terrible -- there is probably a better way
                    // putting this to lowercase because Text search is supposed to be case insensitive
                    final RegexpQuery rq = new RegexpQuery(new Term(key, ".*" + (((String) value).toLowerCase()) + ".*"));
                    params.addQuery(rq);
                } else if (janusgraphPredicate == Cmp.EQUAL) {
                    tokenize(params, map, delegatingAnalyzer, (String) value, key, janusgraphPredicate);
                } else if (janusgraphPredicate == Cmp.NOT_EQUAL) {
                    final BooleanQuery.Builder q = new BooleanQuery.Builder();
                    q.add(new MatchAllDocsQuery(), BooleanClause.Occur.MUST);
                    q.add(new TermQuery(new Term(key, (String) value)), BooleanClause.Occur.MUST_NOT);
                    params.addQuery(q.build());
                } else if (janusgraphPredicate == Text.FUZZY) {
                    params.addQuery(new FuzzyQuery(new Term(key, (String) value)));
                } else if (janusgraphPredicate == Text.CONTAINS_FUZZY) {
                    value = ((String) value).toLowerCase();
                    final Builder b = new BooleanQuery.Builder();
                    for (final String term : Text.tokenize((String) value)) {
                        b.add(new FuzzyQuery(new Term(key, term)), BooleanClause.Occur.MUST);
                    }
                    params.addQuery(b.build());
                } else
                    throw new IllegalArgumentException("Relation is not supported for string value: " + janusgraphPredicate);
            }
        } else if (value instanceof Geoshape) {
            Preconditions.checkArgument(janusgraphPredicate instanceof Geo, "Relation not supported on geo types: " + janusgraphPredicate);
            final Shape shape = ((Geoshape) value).getShape();
            final SpatialOperation spatialOp = SPATIAL_PREDICATES.get(janusgraphPredicate);
            final SpatialArgs args = new SpatialArgs(spatialOp, shape);
            params.addQuery(getSpatialStrategy(key, information.get(key)).makeQuery(args));
        } else if (value instanceof Date) {
            Preconditions.checkArgument(janusgraphPredicate instanceof Cmp, "Relation not supported on date types: " + janusgraphPredicate);
            params.addQuery(numericQuery(key, (Cmp) janusgraphPredicate, ((Date) value).getTime()));
        } else if (value instanceof Instant) {
            Preconditions.checkArgument(janusgraphPredicate instanceof Cmp, "Relation not supported on instant types: " + janusgraphPredicate);
            params.addQuery(numericQuery(key, (Cmp) janusgraphPredicate, ((Instant) value).toEpochMilli()));
        } else if (value instanceof Boolean) {
            Preconditions.checkArgument(janusgraphPredicate instanceof Cmp, "Relation not supported on boolean types: " + janusgraphPredicate);
            final int intValue;
            switch((Cmp) janusgraphPredicate) {
                case EQUAL:
                    intValue = ((Boolean) value) ? 1 : 0;
                    params.addQuery(IntPoint.newRangeQuery(key, intValue, intValue));
                    break;
                case NOT_EQUAL:
                    intValue = ((Boolean) value) ? 0 : 1;
                    params.addQuery(IntPoint.newRangeQuery(key, intValue, intValue));
                    break;
                default:
                    throw new IllegalArgumentException("Boolean types only support EQUAL or NOT_EQUAL");
            }
        } else if (value instanceof UUID) {
            Preconditions.checkArgument(janusgraphPredicate instanceof Cmp, "Relation not supported on UUID types: " + janusgraphPredicate);
            if (janusgraphPredicate == Cmp.EQUAL) {
                params.addQuery(new TermQuery(new Term(key, value.toString())));
            } else if (janusgraphPredicate == Cmp.NOT_EQUAL) {
                final BooleanQuery.Builder q = new BooleanQuery.Builder();
                q.add(new MatchAllDocsQuery(), BooleanClause.Occur.MUST);
                q.add(new TermQuery(new Term(key, value.toString())), BooleanClause.Occur.MUST_NOT);
                params.addQuery(q.build());
            } else {
                throw new IllegalArgumentException("Relation is not supported for UUID type: " + janusgraphPredicate);
            }
        } else {
            throw new IllegalArgumentException("Unsupported type: " + value);
        }
    } else if (condition instanceof Not) {
        final SearchParams childParams = convertQuery(((Not) condition).getChild(), information, delegatingAnalyzer);
        params.addQuery(new MatchAllDocsQuery(), BooleanClause.Occur.MUST);
        params.addParams(childParams, BooleanClause.Occur.MUST_NOT);
    } else if (condition instanceof And) {
        for (final Condition c : condition.getChildren()) {
            final SearchParams childParams = convertQuery(c, information, delegatingAnalyzer);
            params.addParams(childParams, BooleanClause.Occur.MUST);
        }
    } else if (condition instanceof Or) {
        for (final Condition c : condition.getChildren()) {
            final SearchParams childParams = convertQuery(c, information, delegatingAnalyzer);
            params.addParams(childParams, BooleanClause.Occur.SHOULD);
        }
    } else
        throw new IllegalArgumentException("Invalid condition: " + condition);
    return params;
}
Also used : Shape(org.locationtech.spatial4j.shape.Shape) Builder(org.apache.lucene.search.BooleanQuery.Builder) QueryBuilder(org.apache.lucene.util.QueryBuilder) RangeQueryBuilder(org.apache.lucene.queryparser.xml.builders.RangeQueryBuilder) BooleanQueryBuilder(org.apache.lucene.queryparser.xml.builders.BooleanQueryBuilder) Mapping(org.janusgraph.core.schema.Mapping) Builder(org.apache.lucene.search.BooleanQuery.Builder) JanusGraphPredicate(org.janusgraph.graphdb.query.JanusGraphPredicate) SpatialOperation(org.apache.lucene.spatial.query.SpatialOperation) SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) Instant(java.time.Instant)

Example 10 with SpatialOperation

use of org.apache.lucene.spatial.query.SpatialOperation in project elasticsearch by elastic.

the class GeoFilterIT method testRelationSupport.

protected static boolean testRelationSupport(SpatialOperation relation) {
    if (relation == SpatialOperation.IsDisjointTo) {
        // disjoint works in terms of intersection
        relation = SpatialOperation.Intersects;
    }
    try {
        GeohashPrefixTree tree = new GeohashPrefixTree(SpatialContext.GEO, 3);
        RecursivePrefixTreeStrategy strategy = new RecursivePrefixTreeStrategy(tree, "area");
        Shape shape = SpatialContext.GEO.makePoint(0, 0);
        SpatialArgs args = new SpatialArgs(relation, shape);
        strategy.makeQuery(args);
        return true;
    } catch (UnsupportedSpatialOperation e) {
        final SpatialOperation finalRelation = relation;
        ESLoggerFactory.getLogger(GeoFilterIT.class.getName()).info((Supplier<?>) () -> new ParameterizedMessage("Unsupported spatial operation {}", finalRelation), e);
        return false;
    }
}
Also used : SpatialArgs(org.apache.lucene.spatial.query.SpatialArgs) UnsupportedSpatialOperation(org.apache.lucene.spatial.query.UnsupportedSpatialOperation) Shape(org.locationtech.spatial4j.shape.Shape) RecursivePrefixTreeStrategy(org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy) Supplier(org.apache.logging.log4j.util.Supplier) ParameterizedMessage(org.apache.logging.log4j.message.ParameterizedMessage) UnsupportedSpatialOperation(org.apache.lucene.spatial.query.UnsupportedSpatialOperation) SpatialOperation(org.apache.lucene.spatial.query.SpatialOperation) GeohashPrefixTree(org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree)

Aggregations

SpatialOperation (org.apache.lucene.spatial.query.SpatialOperation)12 Shape (org.locationtech.spatial4j.shape.Shape)8 SpatialArgs (org.apache.lucene.spatial.query.SpatialArgs)6 UnsupportedSpatialOperation (org.apache.lucene.spatial.query.UnsupportedSpatialOperation)6 Query (org.apache.lucene.search.Query)5 Test (org.junit.Test)3 Point (org.locationtech.spatial4j.shape.Point)3 Rectangle (org.locationtech.spatial4j.shape.Rectangle)3 Repeat (com.carrotsearch.randomizedtesting.annotations.Repeat)2 BooleanQuery (org.apache.lucene.search.BooleanQuery)2 ConstantScoreQuery (org.apache.lucene.search.ConstantScoreQuery)2 TermQuery (org.apache.lucene.search.TermQuery)2 Instant (java.time.Instant)1 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 ParameterizedMessage (org.apache.logging.log4j.message.ParameterizedMessage)1 Supplier (org.apache.logging.log4j.util.Supplier)1 FieldType (org.apache.lucene.document.FieldType)1 BooleanQueryBuilder (org.apache.lucene.queryparser.xml.builders.BooleanQueryBuilder)1 RangeQueryBuilder (org.apache.lucene.queryparser.xml.builders.RangeQueryBuilder)1