public override void Query(Org.Neo4j.Storageengine.Api.schema.IndexProgressor_NodeValueClient cursor, IndexOrder indexOrder, bool needsValues, params IndexQuery[] predicates) { // Spatial does not support providing values if (needsValues) { throw new System.InvalidOperationException("Spatial index does not support providing values"); } ValidateQuery(indexOrder, predicates); IndexQuery predicate = predicates[0]; SpatialIndexKey treeKeyFrom = layout.newKey(); SpatialIndexKey treeKeyTo = layout.newKey(); InitializeKeys(treeKeyFrom, treeKeyTo); switch (predicate.Type()) { case exists: StartSeekForExists(treeKeyFrom, treeKeyTo, cursor, predicate); break; case exact: StartSeekForExact(treeKeyFrom, treeKeyTo, cursor, ((IndexQuery.ExactPredicate)predicate).value(), predicate); break; case range: IndexQuery.GeometryRangePredicate rangePredicate = (IndexQuery.GeometryRangePredicate)predicate; if (!rangePredicate.Crs().Equals(_spatial.crs)) { throw new System.ArgumentException("IndexQuery on spatial index with mismatching CoordinateReferenceSystem: " + rangePredicate.Crs() + " != " + _spatial.crs); } StartSeekForRange(cursor, rangePredicate, predicates); break; default: throw new System.ArgumentException("IndexQuery of type " + predicate.Type() + " is not supported."); } }
public override void Query(Org.Neo4j.Storageengine.Api.schema.IndexProgressor_NodeValueClient client, IndexOrder indexOrder, bool needsValues, params IndexQuery[] query) { IndexQuery.GeometryRangePredicate geometryRangePredicate = GetGeometryRangePredicateIfAny(query); if (geometryRangePredicate != null) { ValidateQuery(indexOrder, query); try { // If there's a GeometryRangeQuery among the predicates then this query changes from a straight-forward: build from/to and seek... // into a query that is split into multiple sub-queries. Predicates both before and after will have to be accompanied each sub-query. BridgingIndexProgressor multiProgressor = new BridgingIndexProgressor(client, Descriptor.schema().PropertyIds); client.Initialize(Descriptor, multiProgressor, query, indexOrder, needsValues); double[] from = geometryRangePredicate.From() == null ? null : geometryRangePredicate.From().coordinate(); double[] to = geometryRangePredicate.To() == null ? null : geometryRangePredicate.To().coordinate(); CoordinateReferenceSystem crs = geometryRangePredicate.Crs(); SpaceFillingCurve curve = _spaceFillingCurveSettings.forCrs(crs, false); IList <SpaceFillingCurve.LongRange> ranges = curve.GetTilesIntersectingEnvelope(from, to, _configuration); foreach (SpaceFillingCurve.LongRange range in ranges) { // Here's a sub-query that we'll have to do for this geometry range. Build this query from all predicates // and when getting to the geometry range predicate that sparked these sub-query chenanigans, swap in this sub-query in its place. GenericKey treeKeyFrom = Layout.newKey(); GenericKey treeKeyTo = Layout.newKey(); InitializeFromToKeys(treeKeyFrom, treeKeyTo); bool needFiltering = InitializeRangeForGeometrySubQuery(treeKeyFrom, treeKeyTo, query, crs, range); StartSeekForInitializedRange(multiProgressor, treeKeyFrom, treeKeyTo, query, indexOrder, needFiltering, needsValues); } } catch (System.ArgumentException) { // Invalid query ranges will cause this state (eg. min>max) client.Initialize(Descriptor, IndexProgressor.EMPTY, query, indexOrder, needsValues); } } else { base.Query(client, indexOrder, needsValues, query); } }