Skip to content

Commit 829c10f

Browse files
#402 - Implemented double precision and geospatial polygon search with region index
1 parent 8d78ddd commit 829c10f

File tree

3 files changed

+466
-25
lines changed

3 files changed

+466
-25
lines changed

src/main/java/com/marklogic/client/query/StructuredQueryBuilder.java

Lines changed: 179 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,23 @@ public enum Ordering {
8787
ORDERED, UNORDERED;
8888
}
8989

90+
/**
91+
* Geospatial operators to be used in geospatial region index queries
92+
*/
93+
public enum GeoSpatialOperator {
94+
EQUALS, DISJOINT, TOUCHES, CONTAINS, COVERS,
95+
INTERSECTS, WITHIN, COVEREDBY, CROSSES, OVERLAPS;
96+
97+
@Override
98+
public String toString() {
99+
switch(this) {
100+
case COVEREDBY:
101+
return "covered-by";
102+
default:
103+
return this.name().toLowerCase();
104+
}
105+
}
106+
}
90107
/**
91108
* A comparison operator for use in range queries.
92109
*/
@@ -120,6 +137,12 @@ public interface RangeIndex {
120137
*/
121138
public interface GeospatialIndex {
122139
}
140+
/**
141+
* A GeospatialRangeIndex can be used for geospatial region index queries. The
142+
* geospatial region index must be defined in the database configuration.
143+
*/
144+
public interface GeospatialRegionIndex {
145+
}
123146
/**
124147
* A ContainerIndex can be used for container queries.
125148
*/
@@ -595,7 +618,7 @@ public StructuredQueryDefinition range(RangeIndex index, String type, String col
595618
*/
596619
public StructuredQueryDefinition geospatial(GeospatialIndex index, Region... regions) {
597620
checkRegions(regions);
598-
return new GeospatialQuery(index, null, regions, null);
621+
return new GeospatialPointQuery(index, null, regions, null);
599622
}
600623
/**
601624
* Matches an element, element pair, element attribute, pair, or path
@@ -608,7 +631,40 @@ public StructuredQueryDefinition geospatial(GeospatialIndex index, Region... reg
608631
*/
609632
public StructuredQueryDefinition geospatial(GeospatialIndex index, FragmentScope scope, String[] options, Region... regions) {
610633
checkRegions(regions);
611-
return new GeospatialQuery(index, scope, regions, options);
634+
return new GeospatialPointQuery(index, scope, regions, options);
635+
}
636+
637+
638+
/**
639+
* Matches a path specifying a geospatial region, which is indexed via
640+
* geospatial region index, that has the relationship given by the operator
641+
* with at least one of the criteria regions.
642+
* @param index the container for the geospatial regions
643+
* @param operator the geospatial operator to be applied with the regions in the
644+
* index and the specified regions
645+
* @param regions the possible regions containing the region
646+
* @return the StructuredQueryDefinition for the geospatial query
647+
*/
648+
public StructuredQueryDefinition geospatial(GeospatialRegionIndex index, GeoSpatialOperator operator, Region... regions) {
649+
checkRegions(regions);
650+
return new GeospatialRegionQuery((GeoRegionPathImpl)index, operator, null, regions, null);
651+
}
652+
653+
/**
654+
* Matches a path specifying a geospatial region, which is indexed via
655+
* geospatial region index, that has the relationship given by the operator
656+
* with at least one of the criteria regions.
657+
* @param index the container for the geospatial regions
658+
* @param operator the geospatial operator to be applied with the regions in the
659+
* index and the specified regions
660+
* @param scope whether the query matches the document content or properties
661+
* @param options options for fine tuning the query
662+
* @param regions the possible regions containing the region
663+
* @return the StructuredQueryDefinition for the geospatial query
664+
*/
665+
public StructuredQueryDefinition geospatial(GeospatialRegionIndex index, GeoSpatialOperator operator, FragmentScope scope, String[] options, Region... regions) {
666+
checkRegions(regions);
667+
return new GeospatialRegionQuery((GeoRegionPathImpl)index, operator, scope, regions, options);
612668
}
613669

614670
/**
@@ -761,7 +817,17 @@ public GeospatialIndex geoAttributePair(Element parent, Attribute lat, Attribute
761817
* @return the specification for the index on the geospatial coordinates
762818
*/
763819
public GeospatialIndex geoPath(PathIndex pathIndex) {
764-
return new GeoPathImpl(pathIndex);
820+
return new GeoPointPathImpl(pathIndex);
821+
}
822+
823+
/**
824+
* Identifies a path with regions to match
825+
* with a geospatial query.
826+
* @param pathIndex the indexed path
827+
* @return the specification for the index on the geospatial region
828+
*/
829+
public GeospatialRegionIndex geoRegionPath(PathIndex pathIndex) {
830+
return new GeoRegionPathImpl(pathIndex);
765831
}
766832

767833
/**
@@ -940,6 +1006,20 @@ public GeospatialConstraintQuery geospatialConstraint(String constraintName, Reg
9401006
return new GeospatialConstraintQuery(constraintName, regions);
9411007
}
9421008

1009+
/**
1010+
* Matches the container specified by the constraint
1011+
* whose geospatial region appears within one of the criteria regions.
1012+
* @param constraintName the constraint definition
1013+
* @param operator the geospatial operator to be applied with the regions
1014+
* in the index and the criteria regions
1015+
* @param regions the possible regions containing the point
1016+
* @return the StructuredQueryDefinition for the geospatial constraint query
1017+
*/
1018+
public StructuredQueryDefinition geospatialRegionConstraint(String constraintName, GeoSpatialOperator operator, Region... regions) {
1019+
checkRegions(regions);
1020+
return new GeospatialRegionConstraintQuery(constraintName, operator, regions);
1021+
}
1022+
9431023
/**
9441024
* Matches documents as specified by a constraint that implements
9451025
* a custom query parameterized with the supplied text.
@@ -1674,6 +1754,30 @@ public void innerSerialize(XMLStreamWriter serializer) throws Exception {
16741754
}
16751755
}
16761756

1757+
class GeospatialRegionConstraintQuery extends AbstractStructuredQuery {
1758+
String name = null;
1759+
Region[] regions = null;
1760+
GeoSpatialOperator operator;
1761+
1762+
public GeospatialRegionConstraintQuery(String constraintName, GeoSpatialOperator operator, Region... regions) {
1763+
super();
1764+
name = constraintName;
1765+
this.regions = regions;
1766+
this.operator = operator;
1767+
}
1768+
1769+
@Override
1770+
public void innerSerialize(XMLStreamWriter serializer) throws Exception {
1771+
serializer.writeStartElement("geo-region-constraint-query");
1772+
writeText(serializer, "constraint-name", name);
1773+
writeText(serializer, "geospatial-operator", operator.toString());
1774+
for (Region region : regions) {
1775+
((RegionImpl) region).innerSerialize(serializer);
1776+
}
1777+
serializer.writeEndElement();
1778+
}
1779+
}
1780+
16771781
/**
16781782
* @deprecated Use the {@link StructuredQueryDefinition StructuredQueryDefinition} interface
16791783
* as the type for instances of CustomConstraintQuery.
@@ -1872,18 +1976,25 @@ public void innerSerialize(XMLStreamWriter serializer) throws Exception {
18721976
}
18731977
}
18741978

1875-
class GeospatialQuery
1876-
extends AbstractStructuredQuery {
1979+
abstract class GeospatialBaseQuery extends AbstractStructuredQuery {
1980+
FragmentScope scope;
1981+
Region[] regions;
1982+
String[] options;
1983+
1984+
GeospatialBaseQuery(FragmentScope scope, Region[] regions, String[] options) {
1985+
this.scope = scope;
1986+
this.regions = regions;
1987+
this.options = options;
1988+
}
1989+
}
1990+
1991+
class GeospatialPointQuery
1992+
extends GeospatialBaseQuery {
18771993
GeospatialIndex index;
1878-
FragmentScope scope;
1879-
Region[] regions;
1880-
String[] options;
1881-
GeospatialQuery(GeospatialIndex index, FragmentScope scope, Region[] regions,
1994+
GeospatialPointQuery(GeospatialIndex index, FragmentScope scope, Region[] regions,
18821995
String[] options) {
1996+
super(scope, regions, options);
18831997
this.index = index;
1884-
this.scope = scope;
1885-
this.regions = regions;
1886-
this.options = options;
18871998
}
18881999
@Override
18892000
public void innerSerialize(XMLStreamWriter serializer) throws Exception {
@@ -1898,8 +2009,9 @@ else if (index instanceof GeoElementPairImpl)
18982009
elemName = "geo-elem-pair-query";
18992010
else if (index instanceof GeoAttributePairImpl)
19002011
elemName = "geo-attr-pair-query";
1901-
else if (index instanceof GeoPathImpl)
2012+
else if (index instanceof GeoPointPathImpl) {
19022013
elemName = "geo-path-query";
2014+
}
19032015
else
19042016
throw new IllegalStateException(
19052017
"unknown index class: "+index.getClass().getName());
@@ -1918,6 +2030,34 @@ else if (index instanceof GeoPathImpl)
19182030
}
19192031
}
19202032

2033+
class GeospatialRegionQuery extends GeospatialBaseQuery {
2034+
GeoRegionPathImpl index;
2035+
GeoSpatialOperator operator;
2036+
2037+
GeospatialRegionQuery(GeoRegionPathImpl index, GeoSpatialOperator operator, FragmentScope scope,
2038+
Region[] regions, String[] options) {
2039+
super(scope, regions, options);
2040+
this.index = index;
2041+
this.operator = operator;
2042+
}
2043+
2044+
@Override
2045+
public void innerSerialize(XMLStreamWriter serializer) throws Exception {
2046+
String elemName = "geo-region-path-query";
2047+
serializer.writeStartElement(elemName);
2048+
((IndexImpl) index).innerSerialize(serializer);
2049+
writeText(serializer, "geospatial-operator", operator.toString());
2050+
if (scope != null) {
2051+
writeText(serializer, "fragment-scope", scope.toString().toLowerCase());
2052+
}
2053+
writeTextList(serializer, "geo-option", options);
2054+
for (Region region : regions) {
2055+
((RegionImpl) region).innerSerialize(serializer);
2056+
}
2057+
serializer.writeEndElement();
2058+
}
2059+
}
2060+
19212061
class TemporalAxis implements Axis {
19222062
private String name;
19232063
TemporalAxis(String name) {
@@ -2206,17 +2346,32 @@ public void innerSerialize(XMLStreamWriter serializer) throws Exception {
22062346
serializeNamedIndex(serializer, "lon", lonImpl.qname, lonImpl.name);
22072347
}
22082348
}
2209-
2210-
private class GeoPathImpl extends IndexImpl implements GeospatialIndex {
2211-
PathIndex pathIndex;
2212-
GeoPathImpl(PathIndex pathIndex) {
2213-
this.pathIndex = pathIndex;
2214-
}
2215-
@Override
2216-
public void innerSerialize(XMLStreamWriter serializer) throws Exception {
2217-
PathIndexImpl pathIndexImpl = (PathIndexImpl) pathIndex;
2218-
pathIndexImpl.innerSerialize(serializer); ;
2219-
}
2349+
2350+
private class GeoBasePathImpl extends IndexImpl {
2351+
PathIndex pathIndex;
2352+
2353+
GeoBasePathImpl(PathIndex pathIndex) {
2354+
this.pathIndex = pathIndex;
2355+
}
2356+
2357+
@Override
2358+
public void innerSerialize(XMLStreamWriter serializer) throws Exception {
2359+
PathIndexImpl pathIndexImpl = (PathIndexImpl) pathIndex;
2360+
pathIndexImpl.innerSerialize(serializer);
2361+
;
2362+
}
2363+
}
2364+
2365+
private class GeoPointPathImpl extends GeoBasePathImpl implements GeospatialIndex {
2366+
GeoPointPathImpl(PathIndex pathIndex) {
2367+
super(pathIndex);
2368+
}
2369+
}
2370+
2371+
private class GeoRegionPathImpl extends GeoBasePathImpl implements GeospatialRegionIndex {
2372+
GeoRegionPathImpl(PathIndex pathIndex) {
2373+
super(pathIndex);
2374+
}
22202375
}
22212376

22222377
/**

0 commit comments

Comments
 (0)