Skip to content

Add support for spatial point values and distance comparisons #94

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 6, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-opencypher-dsl</artifactId>
<version>1.1.0</version>
<artifactId>neo4j-cypher-dsl</artifactId>
<version>2020.0.1</version>
</dependency>
</dependencies>

Expand Down
2 changes: 1 addition & 1 deletion readme.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ This example doesn't handle introspection queries, but the one in the test direc
* date(time)
* interfaces
* complex filter parameters, with optional query optimization strategy
* spatial

=== Next

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

== Documentation

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package org.neo4j.opencypherdsl
package org.neo4j.cypherdsl.core

import java.util.*

Expand All @@ -7,4 +7,4 @@ class PassThrough(content: String) : Literal<String>(content) {
override fun asString(): String {
return Objects.requireNonNull(content)
}
}
}
19 changes: 17 additions & 2 deletions src/main/kotlin/org/neo4j/graphql/BuildingEnv.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.neo4j.graphql

import graphql.Scalars
import graphql.schema.*

class BuildingEnv(val types: MutableMap<String, GraphQLType>) {
Expand Down Expand Up @@ -95,15 +96,28 @@ class BuildingEnv(val types: MutableMap<String, GraphQLType>) {
if (field.isRelationship()) {
RelationOperator.createRelationFilterFields(type, field, filterType, builder)
} else {
FieldOperator.forType(types[filterType] ?: typeDefinition)
.forEach { op -> builder.addFilterField(op.fieldName(field.name), op.list, filterType) }
val graphQLType = types[filterType] ?: typeDefinition
FieldOperator.forType(graphQLType)
.forEach { op -> builder.addFilterField(op.fieldName(field.name), op.list, filterType, field.description) }
if (graphQLType.isNeo4jSpatialType()) {
val distanceFilterType = getSpatialDistanceFilter(graphQLType)
FieldOperator.forType(distanceFilterType)
.forEach { op -> builder.addFilterField(op.fieldName(field.name + NEO4j_POINT_DISTANCE_FILTER_SUFFIX), op.list, NEO4j_POINT_DISTANCE_FILTER) }
}
}

}
types[filterName] = builder.build()
return filterName
}

private fun getSpatialDistanceFilter(pointType: GraphQLType): GraphQLInputType {
return addInputType(NEO4j_POINT_DISTANCE_FILTER, listOf(
GraphQLFieldDefinition.newFieldDefinition().name("distance").type(GraphQLNonNull(Scalars.GraphQLFloat)).build(),
GraphQLFieldDefinition.newFieldDefinition().name("point").type(GraphQLNonNull(pointType)).build()
))
}

fun addOrdering(type: GraphQLFieldsContainer): String? {
val orderingName = "_${type.name}Ordering"
var existingOrderingType = types[orderingName]
Expand Down Expand Up @@ -163,6 +177,7 @@ class BuildingEnv(val types: MutableMap<String, GraphQLType>) {
GraphQLInputObjectField
.newInputObjectField()
.name(it.name)
.description(it.description)
.type(getInputType(type).ref() as GraphQLInputType)
.build()
}
Expand Down
9 changes: 5 additions & 4 deletions src/main/kotlin/org/neo4j/graphql/GraphQLExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package org.neo4j.graphql
import graphql.Scalars
import graphql.language.*
import graphql.schema.*
import org.neo4j.cypherdsl.core.Node
import org.neo4j.cypherdsl.core.Relationship
import org.neo4j.graphql.DirectiveConstants.Companion.CYPHER
import org.neo4j.graphql.DirectiveConstants.Companion.CYPHER_STATEMENT
import org.neo4j.graphql.DirectiveConstants.Companion.DYNAMIC
Expand All @@ -17,8 +19,6 @@ import org.neo4j.graphql.DirectiveConstants.Companion.RELATION_FROM
import org.neo4j.graphql.DirectiveConstants.Companion.RELATION_NAME
import org.neo4j.graphql.DirectiveConstants.Companion.RELATION_TO
import org.neo4j.graphql.handler.projection.ProjectionBase
import org.neo4j.opencypherdsl.Node
import org.neo4j.opencypherdsl.Relationship

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

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

fun GraphQLFieldDefinition.isRelationship() = !type.isNeo4jType() && this.type.inner().let { it is GraphQLFieldsContainer }
Expand Down Expand Up @@ -262,4 +263,4 @@ fun GraphQLInputObjectType.Builder.addFilterField(fieldName: String, isList: Boo
.description(description)
.type(wrappedType)
this.field(inputField)
}
}
16 changes: 8 additions & 8 deletions src/main/kotlin/org/neo4j/graphql/Neo4jTypes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@ import graphql.language.Field
import graphql.language.ObjectValue
import graphql.schema.GraphQLFieldDefinition
import graphql.schema.GraphQLFieldsContainer
import java.time.*
import java.time.temporal.Temporal

const val NEO4j_FORMATTED_PROPERTY_KEY = "formatted"
const val NEO4j_POINT_DISTANCE_FILTER = "_Neo4jPointDistanceFilter"
const val NEO4j_POINT_DISTANCE_FILTER_SUFFIX = "_distance"

data class TypeDefinition(
val name: String,
val type: Class<out Temporal>,
val typeDefinition: String,
val inputDefinition: String = typeDefinition + "Input"
)
Expand Down Expand Up @@ -75,9 +74,10 @@ data class Neo4jQueryConversion(val name: String, val propertyName: String, val
}

val neo4jTypeDefinitions = listOf(
TypeDefinition("LocalTime", OffsetTime::class.java, "_Neo4jTime"),
TypeDefinition("Date", LocalDate::class.java, "_Neo4jDate"),
TypeDefinition("DateTime", LocalDateTime::class.java, "_Neo4jDateTime"),
TypeDefinition("Time", Instant::class.java, "_Neo4jLocalTime"),
TypeDefinition("LocalDateTime", OffsetDateTime::class.java, "_Neo4jLocalDateTime")
TypeDefinition("LocalTime", "_Neo4jTime"),
TypeDefinition("Date", "_Neo4jDate"),
TypeDefinition("DateTime", "_Neo4jDateTime"),
TypeDefinition("Time", "_Neo4jLocalTime"),
TypeDefinition("LocalDateTime", "_Neo4jLocalDateTime"),
TypeDefinition("Point", "_Neo4jPoint")
)
Loading