Skip to content

Commit

Permalink
Add support for Geo point type in Graphql.
Browse files Browse the repository at this point in the history
  • Loading branch information
arijitAD committed Sep 22, 2020
1 parent 560aa70 commit 72df5bc
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 3 deletions.
17 changes: 16 additions & 1 deletion graphql/schema/dgraph_schemagen_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -606,4 +606,19 @@ schemas:
url: "http://mock:8888/users",
method: "POST"
})
}
}
- name: "geo type."
input: |
type Hotel {
id: ID!
name: String!
location: Point @search
}
output: |
type Hotel {
Hotel.name
Hotel.location
}
Hotel.name: string .
Hotel.location: geo @index(geo) .
23 changes: 23 additions & 0 deletions graphql/schema/gqlschema.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ enum DgraphIndex {
month
day
hour
geo
}
input AuthRule {
Expand Down Expand Up @@ -123,6 +124,25 @@ input CustomHTTP {
skipIntrospection: Boolean
}
type Point {
Latitude: Float!
Longitude: Float!
}
input PointInput {
Latitude: Float!
Longitude: Float!
}
input NearFilter {
Distance: Float!
Coordinate: PointInput!
}
input PointGeoFilter {
near: NearFilter
}
directive @hasInverse(field: String!) on FIELD_DEFINITION
directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION
directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION
Expand Down Expand Up @@ -244,6 +264,7 @@ var supportedSearches = map[string]searchTypeIndex{
"month": {"DateTime", "month"},
"day": {"DateTime", "day"},
"hour": {"DateTime", "hour"},
"geo": {"Point", "geo"},
}

// GraphQL scalar type -> default search arg
Expand All @@ -255,6 +276,7 @@ var defaultSearches = map[string]string{
"Float": "float",
"String": "term",
"DateTime": "year",
"Point": "geo",
}

// graphqlSpecScalars holds all the scalar types supported by the graphql spec.
Expand Down Expand Up @@ -305,6 +327,7 @@ var builtInFilters = map[string]string{
"fulltext": "StringFullTextFilter",
"exact": "StringExactFilter",
"hash": "StringHashFilter",
"geo": "PointGeoFilter",
}

// GraphQL scalar -> Dgraph scalar
Expand Down
9 changes: 8 additions & 1 deletion graphql/schema/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,13 @@ func validateSearchArg(searchArg string,
return nil
}

func isGeoType(typ *ast.Type) bool {
if typ.Name() == "Point" {
return true
}
return false
}

func searchValidation(
sch *ast.Schema,
typ *ast.Definition,
Expand All @@ -961,7 +968,7 @@ func searchValidation(
// If there's no arg, then it can be an enum or has to be a scalar that's
// not ID. The schema generation will add the default search
// for that type.
if sch.Types[field.Type.Name()].Kind == ast.Enum ||
if sch.Types[field.Type.Name()].Kind == ast.Enum || isGeoType(field.Type) ||
(sch.Types[field.Type.Name()].Kind == ast.Scalar && !isIDField(typ, field)) {
return nil
}
Expand Down
7 changes: 6 additions & 1 deletion graphql/schema/schemagen.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,12 @@ func genDgSchema(gqlSch *ast.Schema, definitions []string) string {
var typStr string
switch gqlSch.Types[f.Type.Name()].Kind {
case ast.Object, ast.Interface:
typStr = fmt.Sprintf("%suid%s", prefix, suffix)
if isGeoType(f.Type) {
typStr = "geo"
dgPreds[fname] = getUpdatedPred(fname, typStr, "", []string{"geo"})
} else {
typStr = fmt.Sprintf("%suid%s", prefix, suffix)
}

if parentInt == nil {
if strings.HasPrefix(fname, "~") {
Expand Down
3 changes: 3 additions & 0 deletions graphql/schema/schemagen_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ func TestSchemaString(t *testing.T) {
for _, testFile := range files {
t.Run(testFile.Name(), func(t *testing.T) {
inputFileName := inputDir + testFile.Name()
if testFile.Name() != "geo-type.graphql" {
return
}
str1, err := ioutil.ReadFile(inputFileName)
require.NoError(t, err)

Expand Down
5 changes: 5 additions & 0 deletions graphql/schema/testdata/schemagen/input/geo-type.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type Hotel {
id: ID!
name: String!
location: Point @search
}
258 changes: 258 additions & 0 deletions graphql/schema/testdata/schemagen/output/geo-type.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
#######################
# Input Schema
#######################

type Hotel {
id: ID!
name: String!
location: Point @search
}

#######################
# Extended Definitions
#######################

"""
The Int64 scalar type represents a signed 64‐bit numeric non‐fractional value.
Int64 can represent values in range [-(2^63),(2^63 - 1)].
"""
scalar Int64

"""
The DateTime scalar type represents date and time as a string in RFC3339 format.
For example: "1985-04-12T23:20:50.52Z" represents 20 minutes and 50.52 seconds after the 23rd hour of April 12th, 1985 in UTC.
"""
scalar DateTime

enum DgraphIndex {
int
int64
float
bool
hash
exact
term
fulltext
trigram
regexp
year
month
day
hour
geo
}

input AuthRule {
and: [AuthRule]
or: [AuthRule]
not: AuthRule
rule: String
}

enum HTTPMethod {
GET
POST
PUT
PATCH
DELETE
}

enum Mode {
BATCH
SINGLE
}

input CustomHTTP {
url: String!
method: HTTPMethod!
body: String
graphql: String
mode: Mode
forwardHeaders: [String!]
secretHeaders: [String!]
introspectionHeaders: [String!]
skipIntrospection: Boolean
}

type Point {
Latitude: Float!
Longitude: Float!
}

input PointInput {
Latitude: Float!
Longitude: Float!
}

input NearFilter {
Distance: Float!
Coordinate: PointInput!
}

input PointGeoFilter {
near: NearFilter
}

directive @hasInverse(field: String!) on FIELD_DEFINITION
directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION
directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION
directive @id on FIELD_DEFINITION
directive @withSubscription on OBJECT | INTERFACE
directive @secret(field: String!, pred: String) on OBJECT | INTERFACE
directive @auth(
query: AuthRule,
add: AuthRule,
update: AuthRule,
delete:AuthRule) on OBJECT
directive @custom(http: CustomHTTP, dql: String) on FIELD_DEFINITION
directive @remote on OBJECT | INTERFACE
directive @cascade(fields: [String]) on FIELD

input IntFilter {
eq: Int
le: Int
lt: Int
ge: Int
gt: Int
}

input Int64Filter {
eq: Int64
le: Int64
lt: Int64
ge: Int64
gt: Int64
}

input FloatFilter {
eq: Float
le: Float
lt: Float
ge: Float
gt: Float
}

input DateTimeFilter {
eq: DateTime
le: DateTime
lt: DateTime
ge: DateTime
gt: DateTime
}

input StringTermFilter {
allofterms: String
anyofterms: String
}

input StringRegExpFilter {
regexp: String
}

input StringFullTextFilter {
alloftext: String
anyoftext: String
}

input StringExactFilter {
eq: String
le: String
lt: String
ge: String
gt: String
}

input StringHashFilter {
eq: String
}

#######################
# Generated Types
#######################

type AddHotelPayload {
hotel(filter: HotelFilter, order: HotelOrder, first: Int, offset: Int): [Hotel]
numUids: Int
}

type DeleteHotelPayload {
hotel(filter: HotelFilter, order: HotelOrder, first: Int, offset: Int): [Hotel]
msg: String
numUids: Int
}

type UpdateHotelPayload {
hotel(filter: HotelFilter, order: HotelOrder, first: Int, offset: Int): [Hotel]
numUids: Int
}

#######################
# Generated Enums
#######################

enum HotelHasFilter {
name
location
}

enum HotelOrderable {
name
}

#######################
# Generated Inputs
#######################

input AddHotelInput {
name: String!
}

input HotelFilter {
id: [ID!]
location: PointGeoFilter
has: HotelHasFilter
and: HotelFilter
or: HotelFilter
not: HotelFilter
}

input HotelOrder {
asc: HotelOrderable
desc: HotelOrderable
then: HotelOrder
}

input HotelPatch {
name: String
}

input HotelRef {
id: ID
name: String
}

input UpdateHotelInput {
filter: HotelFilter!
set: HotelPatch
remove: HotelPatch
}

#######################
# Generated Query
#######################

type Query {
getHotel(id: ID!): Hotel
queryHotel(filter: HotelFilter, order: HotelOrder, first: Int, offset: Int): [Hotel]
}

#######################
# Generated Mutations
#######################

type Mutation {
addHotel(input: [AddHotelInput!]!): AddHotelPayload
updateHotel(input: UpdateHotelInput!): UpdateHotelPayload
deleteHotel(filter: HotelFilter!): DeleteHotelPayload
}

0 comments on commit 72df5bc

Please sign in to comment.