From b2ab70cf95faa7d275f26d2032c58e7e1b683d2d Mon Sep 17 00:00:00 2001 From: Arijit Das Date: Wed, 23 Sep 2020 15:19:48 +0530 Subject: [PATCH] Query filter. --- graphql/dgraph/graphquery.go | 3 +++ graphql/resolve/query_rewriter.go | 39 ++++++++++++++++++++++++------- graphql/resolve/query_test.go | 3 +++ graphql/resolve/query_test.yaml | 16 +++++++++++++ graphql/resolve/schema.graphql | 6 +++++ graphql/schema/gqlschema.go | 14 +++++------ 6 files changed, 66 insertions(+), 15 deletions(-) diff --git a/graphql/dgraph/graphquery.go b/graphql/dgraph/graphquery.go index 6d54964cbb8..4222677af7c 100644 --- a/graphql/dgraph/graphquery.go +++ b/graphql/dgraph/graphquery.go @@ -155,6 +155,9 @@ func writeFilterFunction(b *strings.Builder, f *gql.Function) { x.Check2(b.WriteString(fmt.Sprintf("%s(%s)", f.Name, f.Args[0].Value))) case len(f.Args) == 2: x.Check2(b.WriteString(fmt.Sprintf("%s(%s, %s)", f.Name, f.Args[0].Value, f.Args[1].Value))) + case len(f.Args) == 3: + x.Check2(b.WriteString(fmt.Sprintf("%s(%s, %s, %s)", f.Name, f.Args[0].Value, f.Args[1].Value, + f.Args[2].Value))) } } diff --git a/graphql/resolve/query_rewriter.go b/graphql/resolve/query_rewriter.go index 3d835af488b..26f82b3723c 100644 --- a/graphql/resolve/query_rewriter.go +++ b/graphql/resolve/query_rewriter.go @@ -1057,15 +1057,38 @@ func buildFilter(typ schema.Type, filter map[string]interface{}) *gql.FilterTree // OR // numLikes: { le: 10 } -> le(Post.numLikes, 10) fn, val := first(dgFunc) - ands = append(ands, &gql.FilterTree{ - Func: &gql.Function{ - Name: fn, - Args: []gql.Arg{ - {Value: typ.DgraphPredicate(field)}, - {Value: maybeQuoteArg(fn, val)}, + switch fn { + case "near": + geoParams := val.(map[string]interface{}) + distance, _ := geoParams["distance"] + + coordinate, _ := geoParams["coordinate"].(map[string]interface{}) + lat, _ := coordinate["latitude"] + long, _ := coordinate["longitude"] + + args := []gql.Arg{ + {Value: typ.DgraphPredicate(field)}, + {Value: fmt.Sprintf("[%v,%v]", long, lat)}, + {Value: fmt.Sprintf("%v", distance)}, + } + + ands = append(ands, &gql.FilterTree{ + Func: &gql.Function{ + Name: fn, + Args: args, }, - }, - }) + }) + default: + ands = append(ands, &gql.FilterTree{ + Func: &gql.Function{ + Name: fn, + Args: []gql.Arg{ + {Value: typ.DgraphPredicate(field)}, + {Value: maybeQuoteArg(fn, val)}, + }, + }, + }) + } case []interface{}: // ids: [ 0x123, 0x124 ] -> uid(0x123, 0x124) ids := convertIDs(dgFunc) diff --git a/graphql/resolve/query_test.go b/graphql/resolve/query_test.go index a20a74dc79d..0c4828a4abb 100644 --- a/graphql/resolve/query_test.go +++ b/graphql/resolve/query_test.go @@ -56,6 +56,9 @@ func TestQueryRewriting(t *testing.T) { for _, tcase := range tests { t.Run(tcase.Name, func(t *testing.T) { + if tcase.Name != "Geo query" { + return + } op, err := gqlSchema.Operation( &schema.Request{ diff --git a/graphql/resolve/query_test.yaml b/graphql/resolve/query_test.yaml index 1eb0bfabe22..9809505e3a6 100644 --- a/graphql/resolve/query_test.yaml +++ b/graphql/resolve/query_test.yaml @@ -1,3 +1,19 @@ +- + name: "Geo query" + gqlquery: | + query { + queryHotel(filter: { location: { near: { distance: 33.33, coordinate: { latitude: 11.11, longitude: 22.22} } } }) { + name + } + } + dgquery: |- + query { + queryHotel(func: type(Hotel))) @filter(near(Hotel.location, [22.22,11.11], 33.33)) { + name : Hotel.name + dgraph.uid : uid + } + } + - name: "ID query" gqlquery: | diff --git a/graphql/resolve/schema.graphql b/graphql/resolve/schema.graphql index f6e131708da..2d467a04457 100644 --- a/graphql/resolve/schema.graphql +++ b/graphql/resolve/schema.graphql @@ -1,6 +1,12 @@ # Test schema that contains an example of everything that's useful to # test for query rewriting. +type Hotel { + id: ID! + name: String! + location: Point @search +} + type Country { id: ID! name: String! @search(by: [trigram, exact]) diff --git a/graphql/schema/gqlschema.go b/graphql/schema/gqlschema.go index 02c95b9fe5c..d13f4da743c 100644 --- a/graphql/schema/gqlschema.go +++ b/graphql/schema/gqlschema.go @@ -125,22 +125,22 @@ input CustomHTTP { } type Point { - Latitude: Float! - Longitude: Float! + latitude: Float! + longitude: Float! } input PointInput { - Latitude: Float! - Longitude: Float! + latitude: Float! + longitude: Float! } input NearFilter { - Distance: Float! - Coordinate: PointInput! + distance: Float! + coordinate: PointInput! } input PointGeoFilter { - near: NearFilter + near: NearFilter! } directive @hasInverse(field: String!) on FIELD_DEFINITION