Skip to content

Commit 2ad5915

Browse files
authored
Add support for spatial point values and distance comparisons (#94)
* Add support for spatial point values and distance comparisons (resolves #11) * Update neo4j-opencypher-dsl dependency
1 parent 47e7f29 commit 2ad5915

File tree

16 files changed

+979
-117
lines changed

16 files changed

+979
-117
lines changed

pom.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@
115115
</dependency>
116116
<dependency>
117117
<groupId>org.neo4j</groupId>
118-
<artifactId>neo4j-opencypher-dsl</artifactId>
119-
<version>1.1.0</version>
118+
<artifactId>neo4j-cypher-dsl</artifactId>
119+
<version>2020.0.1</version>
120120
</dependency>
121121
</dependencies>
122122

readme.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ This example doesn't handle introspection queries, but the one in the test direc
246246
* date(time)
247247
* interfaces
248248
* complex filter parameters, with optional query optimization strategy
249+
* spatial
249250

250251
=== Next
251252

@@ -254,7 +255,6 @@ This example doesn't handle introspection queries, but the one in the test direc
254255
* input types
255256
* unions
256257
* scalars
257-
* spatial
258258

259259
== Documentation
260260

Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package org.neo4j.opencypherdsl
1+
package org.neo4j.cypherdsl.core
22

33
import java.util.*
44

@@ -7,4 +7,4 @@ class PassThrough(content: String) : Literal<String>(content) {
77
override fun asString(): String {
88
return Objects.requireNonNull(content)
99
}
10-
}
10+
}

src/main/kotlin/org/neo4j/graphql/BuildingEnv.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.neo4j.graphql
22

3+
import graphql.Scalars
34
import graphql.schema.*
45

56
class BuildingEnv(val types: MutableMap<String, GraphQLType>) {
@@ -95,15 +96,28 @@ class BuildingEnv(val types: MutableMap<String, GraphQLType>) {
9596
if (field.isRelationship()) {
9697
RelationOperator.createRelationFilterFields(type, field, filterType, builder)
9798
} else {
98-
FieldOperator.forType(types[filterType] ?: typeDefinition)
99-
.forEach { op -> builder.addFilterField(op.fieldName(field.name), op.list, filterType) }
99+
val graphQLType = types[filterType] ?: typeDefinition
100+
FieldOperator.forType(graphQLType)
101+
.forEach { op -> builder.addFilterField(op.fieldName(field.name), op.list, filterType, field.description) }
102+
if (graphQLType.isNeo4jSpatialType()) {
103+
val distanceFilterType = getSpatialDistanceFilter(graphQLType)
104+
FieldOperator.forType(distanceFilterType)
105+
.forEach { op -> builder.addFilterField(op.fieldName(field.name + NEO4j_POINT_DISTANCE_FILTER_SUFFIX), op.list, NEO4j_POINT_DISTANCE_FILTER) }
106+
}
100107
}
101108

102109
}
103110
types[filterName] = builder.build()
104111
return filterName
105112
}
106113

114+
private fun getSpatialDistanceFilter(pointType: GraphQLType): GraphQLInputType {
115+
return addInputType(NEO4j_POINT_DISTANCE_FILTER, listOf(
116+
GraphQLFieldDefinition.newFieldDefinition().name("distance").type(GraphQLNonNull(Scalars.GraphQLFloat)).build(),
117+
GraphQLFieldDefinition.newFieldDefinition().name("point").type(GraphQLNonNull(pointType)).build()
118+
))
119+
}
120+
107121
fun addOrdering(type: GraphQLFieldsContainer): String? {
108122
val orderingName = "_${type.name}Ordering"
109123
var existingOrderingType = types[orderingName]
@@ -163,6 +177,7 @@ class BuildingEnv(val types: MutableMap<String, GraphQLType>) {
163177
GraphQLInputObjectField
164178
.newInputObjectField()
165179
.name(it.name)
180+
.description(it.description)
166181
.type(getInputType(type).ref() as GraphQLInputType)
167182
.build()
168183
}

src/main/kotlin/org/neo4j/graphql/GraphQLExtensions.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package org.neo4j.graphql
33
import graphql.Scalars
44
import graphql.language.*
55
import graphql.schema.*
6+
import org.neo4j.cypherdsl.core.Node
7+
import org.neo4j.cypherdsl.core.Relationship
68
import org.neo4j.graphql.DirectiveConstants.Companion.CYPHER
79
import org.neo4j.graphql.DirectiveConstants.Companion.CYPHER_STATEMENT
810
import org.neo4j.graphql.DirectiveConstants.Companion.DYNAMIC
@@ -17,8 +19,6 @@ import org.neo4j.graphql.DirectiveConstants.Companion.RELATION_FROM
1719
import org.neo4j.graphql.DirectiveConstants.Companion.RELATION_NAME
1820
import org.neo4j.graphql.DirectiveConstants.Companion.RELATION_TO
1921
import org.neo4j.graphql.handler.projection.ProjectionBase
20-
import org.neo4j.opencypherdsl.Node
21-
import org.neo4j.opencypherdsl.Relationship
2222

2323
fun Type<Type<*>>.name(): String? = if (this.inner() is TypeName) (this.inner() as TypeName).name else null
2424
fun Type<Type<*>>.inner(): Type<Type<*>> = when (this) {
@@ -35,7 +35,8 @@ fun GraphQLType.inner(): GraphQLType = when (this) {
3535

3636
fun GraphQLType.isList() = this is GraphQLList || (this is GraphQLNonNull && this.wrappedType is GraphQLList)
3737
fun GraphQLType.isScalar() = this.inner().let { it is GraphQLScalarType || it.name.startsWith("_Neo4j") }
38-
fun GraphQLType.isNeo4jType() = this.inner().name?.startsWith("_Neo4j") == true
38+
fun GraphQLType.isNeo4jType() = this.innerName().startsWith("_Neo4j")
39+
fun GraphQLType.isNeo4jSpatialType() = this.innerName().startsWith("_Neo4jPoint")
3940
fun GraphQLFieldDefinition.isNeo4jType(): Boolean = this.type.isNeo4jType()
4041

4142
fun GraphQLFieldDefinition.isRelationship() = !type.isNeo4jType() && this.type.inner().let { it is GraphQLFieldsContainer }
@@ -262,4 +263,4 @@ fun GraphQLInputObjectType.Builder.addFilterField(fieldName: String, isList: Boo
262263
.description(description)
263264
.type(wrappedType)
264265
this.field(inputField)
265-
}
266+
}

src/main/kotlin/org/neo4j/graphql/Neo4jTypes.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ import graphql.language.Field
44
import graphql.language.ObjectValue
55
import graphql.schema.GraphQLFieldDefinition
66
import graphql.schema.GraphQLFieldsContainer
7-
import java.time.*
8-
import java.time.temporal.Temporal
97

108
const val NEO4j_FORMATTED_PROPERTY_KEY = "formatted"
9+
const val NEO4j_POINT_DISTANCE_FILTER = "_Neo4jPointDistanceFilter"
10+
const val NEO4j_POINT_DISTANCE_FILTER_SUFFIX = "_distance"
1111

1212
data class TypeDefinition(
1313
val name: String,
14-
val type: Class<out Temporal>,
1514
val typeDefinition: String,
1615
val inputDefinition: String = typeDefinition + "Input"
1716
)
@@ -75,9 +74,10 @@ data class Neo4jQueryConversion(val name: String, val propertyName: String, val
7574
}
7675

7776
val neo4jTypeDefinitions = listOf(
78-
TypeDefinition("LocalTime", OffsetTime::class.java, "_Neo4jTime"),
79-
TypeDefinition("Date", LocalDate::class.java, "_Neo4jDate"),
80-
TypeDefinition("DateTime", LocalDateTime::class.java, "_Neo4jDateTime"),
81-
TypeDefinition("Time", Instant::class.java, "_Neo4jLocalTime"),
82-
TypeDefinition("LocalDateTime", OffsetDateTime::class.java, "_Neo4jLocalDateTime")
77+
TypeDefinition("LocalTime", "_Neo4jTime"),
78+
TypeDefinition("Date", "_Neo4jDate"),
79+
TypeDefinition("DateTime", "_Neo4jDateTime"),
80+
TypeDefinition("Time", "_Neo4jLocalTime"),
81+
TypeDefinition("LocalDateTime", "_Neo4jLocalDateTime"),
82+
TypeDefinition("Point", "_Neo4jPoint")
8383
)

0 commit comments

Comments
 (0)