diff --git a/graphql/dgraph/graphquery.go b/graphql/dgraph/graphquery.go index 99bb6352147..23519f45a78 100644 --- a/graphql/dgraph/graphquery.go +++ b/graphql/dgraph/graphquery.go @@ -28,12 +28,16 @@ import ( // validate query, and so doesn't return an error if query is 'malformed' - it might // just write something that wouldn't parse as a Dgraph query. func AsString(queries []*dql.GraphQuery) string { - if queries == nil { + if len(queries) == 0 { return "" } var b strings.Builder - x.Check2(b.WriteString("query {\n")) + queryName := queries[len(queries)-1].Attr + x.Check2(b.WriteString("query ")) + addQueryVars(&b, queryName, queries[0].Args) + x.Check2(b.WriteString("{\n")) + numRewrittenQueries := 0 for _, q := range queries { if q == nil { @@ -54,6 +58,24 @@ func AsString(queries []*dql.GraphQuery) string { return b.String() } +func addQueryVars(b *strings.Builder, queryName string, args map[string]string) { + dollarFound := false + for name, val := range args { + if strings.HasPrefix(name, "$") { + if !dollarFound { + x.Check2(b.WriteString(queryName + "(")) + x.Check2(b.WriteString(name + ": " + val)) + dollarFound = true + } else { + x.Check2(b.WriteString(", " + name + ": " + val)) + } + } + } + if dollarFound { + x.Check2(b.WriteString(") ")) + } +} + func writeQuery(b *strings.Builder, query *dql.GraphQuery, prefix string) { if query.Var != "" || query.Alias != "" || query.Attr != "" { x.Check2(b.WriteString(prefix)) @@ -145,6 +167,9 @@ func writeRoot(b *strings.Builder, q *dql.GraphQuery) { } switch { + // TODO: Instead of the hard-coded strings "uid", "type", etc., use the + // pre-defined constants in dql/parser.go such as dql.uidFunc, dql.typFunc, + // etc. This of course will require that we make these constants public. case q.Func.Name == "uid": x.Check2(b.WriteString("(func: ")) writeUIDFunc(b, q.Func.UID, q.Func.Args) @@ -154,6 +179,10 @@ func writeRoot(b *strings.Builder, q *dql.GraphQuery) { x.Check2(b.WriteString("(func: eq(")) writeFilterArguments(b, q.Func.Args) x.Check2(b.WriteRune(')')) + case q.Func.Name == "similar_to": + x.Check2(b.WriteString("(func: similar_to(")) + writeFilterArguments(b, q.Func.Args) + x.Check2(b.WriteRune(')')) } writeOrderAndPage(b, q, true) x.Check2(b.WriteRune(')')) diff --git a/graphql/e2e/schema/apollo_service_response.graphql b/graphql/e2e/schema/apollo_service_response.graphql index c0383cdeec5..6a35c223770 100644 --- a/graphql/e2e/schema/apollo_service_response.graphql +++ b/graphql/e2e/schema/apollo_service_response.graphql @@ -197,6 +197,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/e2e/schema/generatedSchema.graphql b/graphql/e2e/schema/generatedSchema.graphql index 6b9c37d5f31..9cdc8e0c8fd 100644 --- a/graphql/e2e/schema/generatedSchema.graphql +++ b/graphql/e2e/schema/generatedSchema.graphql @@ -178,6 +178,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/resolve/mutation_rewriter.go b/graphql/resolve/mutation_rewriter.go index 669cfafa6ae..a5914347b76 100644 --- a/graphql/resolve/mutation_rewriter.go +++ b/graphql/resolve/mutation_rewriter.go @@ -1675,6 +1675,12 @@ func rewriteObject( fieldName = fieldName[1 : len(fieldName)-1] } + if fieldDef.HasEmbeddingDirective() { + // embedding is a JSON array of numbers. Rewrite it as a string, for now + var valBytes []byte + valBytes, _ = json.Marshal(val) + val = string(valBytes) + } // TODO: Write a function for aggregating data of fragment from child nodes. switch val := val.(type) { case map[string]interface{}: diff --git a/graphql/resolve/query_rewriter.go b/graphql/resolve/query_rewriter.go index e58f03ab73b..9c94b3e1b1c 100644 --- a/graphql/resolve/query_rewriter.go +++ b/graphql/resolve/query_rewriter.go @@ -19,6 +19,7 @@ package resolve import ( "bytes" "context" + "encoding/json" "fmt" "sort" "strconv" @@ -147,7 +148,14 @@ func (qr *queryRewriter) Rewrite( dgQuery := rewriteAsGet(gqlQuery, uid, xid, authRw) return dgQuery, nil - + case schema.SimilarByIdQuery: + xid, uid, err := gqlQuery.IDArgValue() + if err != nil { + return nil, err + } + return rewriteAsSimilarByIdQuery(gqlQuery, uid, xid, authRw), nil + case schema.SimilarByEmbeddingQuery: + return rewriteAsSimilarByEmbeddingQuery(gqlQuery, authRw), nil case schema.FilterQuery: return rewriteAsQuery(gqlQuery, authRw), nil case schema.PasswordQuery: @@ -612,6 +620,268 @@ func rewriteAsGet( return dgQuery } +// rewriteAsSimilarByIdQuery +// +// rewrites SimilarById graphQL query to nested DQL query blocks +// Example rewrittern query: +// +// query { +// var(func: eq(Product.id, "0528012398")) @filter(type(Product)) { +// vec as Product.embedding +// } +// var() { +// v1 as max(val(vec)) +// } +// var(func: similar_to(Product.embedding, 8, val(v1))) { +// v2 as Product.embedding +// distance as math((v2 - v1) dot (v2 - v1)) +// } +// querySimilarProductById(func: uid(distance), orderasc: val(distance)) { +// ProductWithDistance.id : Product.id +// ProductWithDistance.description : Product.description +// ProductWithDistance.title : Product.title +// ProductWithDistance.imageUrl : Product.imageUrl +// ProductWithDistance.hm_distance : val(distance) +// dgraph.uid : uid +// } +// } +func rewriteAsSimilarByIdQuery( + query schema.Query, + uid uint64, + xidArgToVal map[string]string, + auth *authRewriter) []*dql.GraphQuery { + + // Get graphQL arguments + typ := query.Type() + pred := typ.DgraphPredicate(query.ArgValue(schema.SimilarByArgName).(string)) + topK := query.ArgValue(schema.SimilarTopKArgName).(int64) + + // First generate the query to fetch the uid + // for the given id. For Example, + // var(func: eq(Product.id, "0528012398")) @filter(type(Product)) { + // vec as Product.embedding + // } + dgQuery := rewriteAsGet(query, uid, xidArgToVal, auth) + lastQuery := dgQuery[len(dgQuery)-1] + // Turn the root query into "var" + lastQuery.Attr = "var" + // Save the result to be later used for the last query block, sortQuery + result := lastQuery.Children + + // define the variable "vec" for the search vector + lastQuery.Children = []*dql.GraphQuery{{ + Attr: pred, + Var: "vec", + }} + + // Turn the variable into a "const" by + // remembering the max of it. + // The lookup is going to return exactly one uid + // anyway. For example, + // var() { + // v1 as max(val(vec)) + // } + aggQuery := &dql.GraphQuery{ + Attr: "var" + "()", + Children: []*dql.GraphQuery{ + { + Var: "v1", + Attr: "max(val(vec))", + }, + }, + } + + // Similar_to query, computes the distance for + // ordering the result later. + // Example: + // var(func: similar_to(Product.embedding, 8, val(v1))) { + // v2 as Product.embedding + // distance as math((v2 - v1) dot (v2 - v1)) + // } + similarQuery := &dql.GraphQuery{ + Attr: "var", + Children: []*dql.GraphQuery{ + { + Var: "v2", + Attr: pred, + }, + { + Var: "distance", + Attr: "math((v2 - v1) dot (v2 - v1))", + }, + }, + Func: &dql.Function{ + Name: "similar_to", + Args: []dql.Arg{ + { + Value: pred, + }, + { + Value: fmt.Sprintf("%d", topK), + }, + { + Value: "val(v1)", + }, + }, + }, + } + + // Rename the distance as .hm_distance + distance := &dql.GraphQuery{ + Alias: typ.Name() + "." + schema.SimilarQueryDistanceFieldName, + Attr: "val(distance)", + } + + var found bool = false + for _, child := range result { + if child.Alias == typ.Name()+"."+schema.SimilarQueryDistanceFieldName { + child.Attr = "val(distance)" + found = true + break + } + } + if !found { + result = append(result, distance) + } + + // order the result by euclidian distance, For example, + // querySimilarProductById(func: uid(distance), orderasc: val(distance)) { + // ProductWithDistance.id : Product.id + // ProductWithDistance.description : Product.description + // ProductWithDistance.title : Product.title + // ProductWithDistance.imageUrl : Product.imageUrl + // ProductWithDistance.hm_distance : val(distance) + // dgraph.uid : uid + // } + // } + sortQuery := &dql.GraphQuery{ + Attr: query.DgraphAlias(), + Children: result, + Func: &dql.Function{ + Name: "uid", + Args: []dql.Arg{{Value: "distance"}}, + }, + Order: []*pb.Order{{Attr: "val(distance)", Desc: false}}, + } + + dgQuery = append(dgQuery, aggQuery, similarQuery, sortQuery) + return dgQuery +} + +// rewriteAsSimilarByEmbeddingQuery +// +// rewrites SimilarByEmbedding graphQL query to nested DQL query blocks +// Example rewrittern query: +// +// query gQLTodQL($search_vector: vfloat = "") { +// var(func: similar_to(Product.embedding, 8, $search_vector)) { +// v2 as Product.embedding +// distance as math((v2 - $search_vector) dot (v2 - $search_vector)) +// } +// querySimilarProductById(func: uid(distance), orderasc: val(distance)) { +// ProductWithDistance.id : Product.id +// ProductWithDistance.description : Product.description +// ProductWithDistance.title : Product.title +// ProductWithDistance.imageUrl : Product.imageUrl +// ProductWithDistance.hm_distance : val(distance) +// dgraph.uid : uid +// } +// } +func rewriteAsSimilarByEmbeddingQuery( + query schema.Query, auth *authRewriter) []*dql.GraphQuery { + + dgQuery := rewriteAsQuery(query, auth) + + // Remember dgQuery[0].Children as result type for the last block + // in the rewritten query + result := dgQuery[0].Children + typ := query.Type() + + // Get all the arguments from graphQL query + pred := typ.DgraphPredicate(query.ArgValue(schema.SimilarByArgName).(string)) + topK := query.ArgValue(schema.SimilarTopKArgName).(int64) + vec := query.ArgValue(schema.SimilarVectorArgName).([]interface{}) + vecStr, _ := json.Marshal(vec) + + // Save vectorString as a query variable, $search_vector + queryArgs := dgQuery[0].Args + if queryArgs == nil { + queryArgs = make(map[string]string) + } + queryArgs["$search_vector"] = " vfloat = \"" + string(vecStr) + "\"" + thisFilter := &dql.FilterTree{ + Func: dgQuery[0].Func, + } + + // create the similar_to function and move existing root function + // to the filter tree + addToFilterTree(dgQuery[0], thisFilter) + + // Create similar_to as the root function, passing $search_vector as + // the search vector + dgQuery[0].Attr = "var" + dgQuery[0].Func = &dql.Function{ + Name: "similar_to", + Args: []dql.Arg{ + { + Value: pred, + }, + { + Value: fmt.Sprintf("%d", topK), + }, + { + Value: "$search_vector", + }, + }, + } + + // Compute the euclidian distance between the neighbor + // and the search vector + dgQuery[0].Children = []*dql.GraphQuery{ + { + Var: "v2", + Attr: pred, + }, + { + Var: "distance", + // TODO: generate different math formula based on index type + Attr: "math((v2 - $search_vector) dot (v2 - $search_vector))", + }, + } + + // Rename distance as .hm_distance + distance := &dql.GraphQuery{ + Alias: typ.Name() + "." + schema.SimilarQueryDistanceFieldName, + Attr: "val(distance)", + } + + var found bool = false + for _, child := range result { + if child.Alias == typ.Name()+"."+schema.SimilarQueryDistanceFieldName { + child.Attr = "val(distance)" + found = true + break + } + } + if !found { + result = append(result, distance) + } + + // order by distance + sortQuery := &dql.GraphQuery{ + Attr: query.DgraphAlias(), + Children: result, + Func: &dql.Function{ + Name: "uid", + Args: []dql.Arg{{Value: "distance"}}, + }, + Order: []*pb.Order{{Attr: "val(distance)", Desc: false}}, + } + + dgQuery = append(dgQuery, sortQuery) + return dgQuery +} + // Adds common RBAC and UID, Type rules to DQL query. // This function is used by rewriteAsQuery and aggregateQuery functions func addCommonRules( diff --git a/graphql/resolve/resolver.go b/graphql/resolve/resolver.go index 7b0936ec755..79dd12b16ab 100644 --- a/graphql/resolve/resolver.go +++ b/graphql/resolve/resolver.go @@ -235,6 +235,8 @@ func (rf *resolverFactory) WithConventionResolvers( s schema.Schema, fns *ResolverFns) ResolverFactory { queries := append(s.Queries(schema.GetQuery), s.Queries(schema.FilterQuery)...) + queries = append(queries, s.Queries(schema.SimilarByIdQuery)...) + queries = append(queries, s.Queries(schema.SimilarByEmbeddingQuery)...) queries = append(queries, s.Queries(schema.PasswordQuery)...) queries = append(queries, s.Queries(schema.AggregateQuery)...) for _, q := range queries { diff --git a/graphql/schema/gqlschema.go b/graphql/schema/gqlschema.go index 7927f547e64..1b0f1241369 100644 --- a/graphql/schema/gqlschema.go +++ b/graphql/schema/gqlschema.go @@ -34,9 +34,10 @@ const ( searchDirective = "search" searchArgs = "by" - dgraphDirective = "dgraph" - dgraphTypeArg = "type" - dgraphPredArg = "pred" + dgraphDirective = "dgraph" + dgraphTypeArg = "type" + dgraphPredArg = "pred" + embeddingDirective = "hm_embedding" idDirective = "id" idDirectiveInterfaceArg = "interface" @@ -276,6 +277,7 @@ input GenerateMutationParams { directiveDefs = ` directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION @@ -307,6 +309,7 @@ directive @generate( apolloSupportedDirectiveDefs = ` directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION @@ -561,6 +564,7 @@ func ValidatorNoOp( var directiveValidators = map[string]directiveValidator{ inverseDirective: hasInverseValidation, searchDirective: searchValidation, + embeddingDirective: embeddingValidation, dgraphDirective: dgraphDirectiveValidation, idDirective: idValidation, subscriptionDirective: ValidatorNoOp, @@ -1671,6 +1675,10 @@ func hasXID(defn *ast.Definition) bool { return fieldAny(nonExternalAndKeyFields(defn), hasIDDirective) } +func hasEmbedding(defn *ast.Definition) bool { + return fieldAny(nonExternalAndKeyFields(defn), hasEmbeddingDirective) +} + // fieldAny returns true if any field in fields satisfies pred func fieldAny(fields ast.FieldList, pred func(*ast.FieldDefinition) bool) bool { for _, fld := range fields { @@ -1945,7 +1953,8 @@ func addAggregationResultType(schema *ast.Schema, defn *ast.Definition, provides } } -func addGetQuery(schema *ast.Schema, defn *ast.Definition, providesTypeMap map[string]bool, generateSubscription bool) { +func addGetQuery(schema *ast.Schema, defn *ast.Definition, + providesTypeMap map[string]bool, generateSubscription bool) { hasIDField := hasID(defn) hasXIDField := hasXID(defn) xidCount := xidsCount(defn.Fields) @@ -2006,6 +2015,227 @@ func addGetQuery(schema *ast.Schema, defn *ast.Definition, providesTypeMap map[s } } +// addSimilarByEmbeddingQuery adds a query to perform similarity based search on +// a specified embedding as an array of floats +// schema - the graphQL schema. The schema will be modified by this operation +// defn - The type definition for the object for which this query will be added +func addSimilarByEmbeddingQuery(schema *ast.Schema, defn *ast.Definition) { + + // Generate the new for similarity search results. This is done by + // adding a new field to + // the input type. The new field is "hm_distance". The name of the new type + // is WithDistance + fields := append(defn.Fields, + &ast.FieldDefinition{ + Name: SimilarQueryDistanceFieldName, + Type: &ast.Type{NamedType: "Float"}}) + // Add dgraph directive for the new type WithDistance. + // @dgraph(type: ) + args := []*ast.Argument{} + args = append(args, &ast.Argument{ + Name: "type", + Value: &ast.Value{Kind: ast.StringValue, Raw: defn.Name}}) + dir := &ast.Directive{ + Name: dgraphDirective, + Arguments: args, + } + + // new type, WithDistance + resultTypeName := defn.Name + SimilarQueryResultTypeSuffix + resultType := &ast.Definition{ + Kind: ast.Object, + Name: resultTypeName, + Fields: fields, + Directives: []*ast.Directive{dir}, + } + + // create the new query, querySimilarByEmbedding + schema.Types[resultTypeName] = resultType + qry := &ast.FieldDefinition{ + Name: SimilarQueryPrefix + defn.Name + SimilarByEmbeddingQuerySuffix, + Type: &ast.Type{ + Elem: &ast.Type{ + NamedType: resultTypeName, + }, + }, + } + + // Define the enum to + //select from among all predicates with "@hm_embedding" directives + enumName := defn.Name + EmbeddingEnumSuffix + enum := &ast.Definition{ + Kind: ast.Enum, + Name: enumName, + } + + for _, fld := range defn.Fields { + if hasEmbeddingDirective(fld) { + enum.EnumValues = append(enum.EnumValues, + &ast.EnumValueDefinition{Name: fld.Name}) + } + } + schema.Types[enumName] = enum + + //Accept the name of embedding field + qry.Arguments = append(qry.Arguments, &ast.ArgumentDefinition{ + Name: SimilarByArgName, + Type: &ast.Type{NamedType: enumName}, + }) + + // Accept the topK, number of nearest neighbors to + // return + qry.Arguments = append(qry.Arguments, &ast.ArgumentDefinition{ + Name: SimilarTopKArgName, + Type: &ast.Type{ + NamedType: "Int", + NonNull: true, + }, + }) + + // Accept an array of floats as the search vector + qry.Arguments = append(qry.Arguments, &ast.ArgumentDefinition{ + Name: SimilarVectorArgName, + Type: &ast.Type{ + Elem: &ast.Type{ + NamedType: "Float", + NonNull: true, + }, + }, + }) + + schema.Query.Fields = append(schema.Query.Fields, qry) +} + +// addSimilarByIdQuery adds a query that looks up a node based on an id/xid. +// The query then performs a similarity search based on the value of the +// selected embedding field to find similar objects +// schema - The graphQL schema. New enums and result type are added to the schema +// defn - The object type for which the query is added +func addSimilarByIdQuery(schema *ast.Schema, defn *ast.Definition, + providesTypeMap map[string]bool) { + hasIDField := hasID(defn) + hasXIDField := hasXID(defn) + xidCount := xidsCount(defn.Fields) + if !hasIDField && !hasXIDField { + return + } + + // Generate the new for similarity search results. This is done by + // adding a new field to the input type. The new field is "hm_distance". + // The name of the new type is WithDistance + fields := append(defn.Fields, + &ast.FieldDefinition{ + Name: SimilarQueryDistanceFieldName, + Type: &ast.Type{NamedType: "Float"}}) + + // Add dgraph directive for the new type WithDistance. + // @dgraph(type: ) + args := []*ast.Argument{} + args = append(args, + &ast.Argument{ + Name: "type", + Value: &ast.Value{Kind: ast.StringValue, Raw: defn.Name}}) + dir := &ast.Directive{ + Name: dgraphDirective, + Arguments: args, + } + + // new type, WithDistance + resultTypeName := defn.Name + SimilarQueryResultTypeSuffix + resultType := &ast.Definition{ + Kind: ast.Object, + Name: resultTypeName, + Fields: fields, + Directives: []*ast.Directive{dir}, + } + schema.Types[resultTypeName] = resultType + + // create the new query, querySimilarById + qry := &ast.FieldDefinition{ + Name: SimilarQueryPrefix + defn.Name + SimilarByIdQuerySuffix, + Type: &ast.Type{ + Elem: &ast.Type{ + NamedType: resultTypeName, + }, + }, + } + + // If the defn, only specified one of ID/XID field, then they are mandatory. + // If it specified both, then they are optional. + if hasIDField { + fields := getIDField(defn, providesTypeMap) + qry.Arguments = append(qry.Arguments, &ast.ArgumentDefinition{ + Name: fields[0].Name, + Type: &ast.Type{ + NamedType: idTypeFor(defn), + NonNull: !hasXIDField, + }, + }) + } + + if hasXIDField { + var idWithoutUniqueArgExists bool + for _, fld := range defn.Fields { + if hasIDDirective(fld) { + if !hasInterfaceArg(fld) { + idWithoutUniqueArgExists = true + } + qry.Arguments = append(qry.Arguments, &ast.ArgumentDefinition{ + Name: fld.Name, + Type: &ast.Type{ + NamedType: fld.Type.Name(), + NonNull: !hasIDField && xidCount <= 1, + }, + }) + } + } + if defn.Kind == "INTERFACE" && idWithoutUniqueArgExists { + qry.Directives = append( + qry.Directives, &ast.Directive{Name: deprecatedDirective, + Arguments: ast.ArgumentList{&ast.Argument{Name: "reason", + Value: &ast.Value{Raw: "@id argument for get query on interface is being" + + " deprecated. Only those @id fields which have interface argument" + + " set to true will be available in getQuery argument on interface" + + " post v21.11.0, please update your schema accordingly.", + Kind: ast.StringValue}}}}) + } + } + + // Define the enum to + //select from among all predicates with "@hm_embedding" directives + enumName := defn.Name + EmbeddingEnumSuffix + enum := &ast.Definition{ + Kind: ast.Enum, + Name: enumName, + } + + for _, fld := range defn.Fields { + if hasEmbeddingDirective(fld) { + enum.EnumValues = append(enum.EnumValues, + &ast.EnumValueDefinition{Name: fld.Name}) + } + } + schema.Types[enumName] = enum + + // Accept the name of the embedding field. + qry.Arguments = append(qry.Arguments, &ast.ArgumentDefinition{ + Name: SimilarByArgName, + Type: &ast.Type{NamedType: enumName}, + }) + + // Accept the topK, number of nearest neighbors to + // return + qry.Arguments = append(qry.Arguments, &ast.ArgumentDefinition{ + Name: SimilarTopKArgName, + Type: &ast.Type{ + NamedType: "Int", + NonNull: true, + }, + }) + + schema.Query.Fields = append(schema.Query.Fields, qry) +} + func addFilterQuery( schema *ast.Schema, defn *ast.Definition, @@ -2032,7 +2262,8 @@ func addFilterQuery( } -func addAggregationQuery(schema *ast.Schema, defn *ast.Definition, generateSubscription bool) { +func addAggregationQuery(schema *ast.Schema, + defn *ast.Definition, generateSubscription bool) { qry := &ast.FieldDefinition{ Name: "aggregate" + defn.Name, Type: &ast.Type{ @@ -2049,7 +2280,8 @@ func addAggregationQuery(schema *ast.Schema, defn *ast.Definition, generateSubsc } -func addPasswordQuery(schema *ast.Schema, defn *ast.Definition, providesTypeMap map[string]bool) { +func addPasswordQuery(schema *ast.Schema, + defn *ast.Definition, providesTypeMap map[string]bool) { hasIDField := hasID(defn) hasXIDField := hasXID(defn) if !hasIDField && !hasXIDField { @@ -2095,6 +2327,10 @@ func addQueries( ) { if params.generateGetQuery { addGetQuery(schema, defn, providesTypeMap, params.generateSubscription) + if hasEmbedding(defn) { + addSimilarByIdQuery(schema, defn, providesTypeMap) + addSimilarByEmbeddingQuery(schema, defn) + } } if params.generatePasswordQuery { diff --git a/graphql/schema/gqlschema_test.yml b/graphql/schema/gqlschema_test.yml index 64f918f05e7..eb69c0ba608 100644 --- a/graphql/schema/gqlschema_test.yml +++ b/graphql/schema/gqlschema_test.yml @@ -2732,7 +2732,7 @@ invalid_schemas: review: String! } errlist: [ - {"message": "Type Product; @remote directive cannot be defined with @key directive", "locations": [ { "line": 174, "column": 12} ] }, + {"message": "Type Product; @remote directive cannot be defined with @key directive", "locations": [ { "line": 175, "column": 12} ] }, ] - name: "directives defined on @external fields that are not @key." @@ -2751,6 +2751,29 @@ invalid_schemas: {"message": "Type Product: Field name: @search directive can not be defined on @external fields that are not @key.", "locations": [ { "line": 3, "column": 18} ] }, ] + - name: "@hm_embedding directive on a field with String type" + input: | + type Product { + id: String! @id + description: String + title: String + productVector: String @hm_embedding + } + errlist: [ + {"message": "Type Product; Field productVector: The field with @hm_embedding directive is of type String, but @hm_embedding directive only applies to fields of type [Float].", "locations": [ { "line": 5, "column": 3} ] }, + ] + + - name: "@hm_embedding directive on a field with [Int] type" + input: | + type User { + email: String! @id + name: String + userVector: [Int] @hm_embedding + } + errlist: [ + {"message": "Type User; Field userVector: The field with @hm_embedding directive is of type [Int], but @hm_embedding directive only applies to fields of type [Float].", "locations": [ { "line": 4, "column": 3} ] }, + ] + - name: "@requires directive defined on type definitions" input: | type Product @key(fields: "id"){ diff --git a/graphql/schema/rules.go b/graphql/schema/rules.go index 78518d11821..86f67118511 100644 --- a/graphql/schema/rules.go +++ b/graphql/schema/rules.go @@ -829,6 +829,32 @@ func listValidityCheck(typ *ast.Definition, field *ast.FieldDefinition) gqlerror return nil } +func embeddingValidation(sch *ast.Schema, typ *ast.Definition, + field *ast.FieldDefinition, dir *ast.Directive, + secrets map[string]x.Sensitive) gqlerror.List { + var errs []*gqlerror.Error + if field.Type.Elem == nil { + errs = append(errs, + gqlerror.ErrorPosf( + field.Position, + "Type %s; Field %s: The field with @hm_embedding directive is of type %s,"+ + " but @hm_embedding directive only applies"+ + " to fields of type [Float].", typ.Name, field.Name, field.Type.Name())) + return errs + } + + if !strings.EqualFold(field.Type.Elem.NamedType, "Float") { + errs = append(errs, + gqlerror.ErrorPosf( + field.Position, + "Type %s; Field %s: The field with @hm_embedding directive is of type [%s], "+ + "but @hm_embedding directive only applies"+ + " to fields of type [Float].", typ.Name, field.Name, field.Type.Name())) + } + + return errs +} + func hasInverseValidation(sch *ast.Schema, typ *ast.Definition, field *ast.FieldDefinition, dir *ast.Directive, secrets map[string]x.Sensitive) gqlerror.List { diff --git a/graphql/schema/schemagen.go b/graphql/schema/schemagen.go index 76b9a30fd96..0f6249cd088 100644 --- a/graphql/schema/schemagen.go +++ b/graphql/schema/schemagen.go @@ -669,6 +669,15 @@ func genDgSchema(gqlSch *ast.Schema, definitions []string, } } + embedding := f.Directives.ForName(embeddingDirective) + if embedding != nil { + // embeddingValidation ensured GQL type is [Float] + // set typStr to vfloat + typStr = "vfloat" + // Appropriate index will be created through embedding services + // indexes = append(indexes, "hnsw-euclidian") + } + if parentInt == nil { // if field name contains @ then it is a language tagged field. isLang := false diff --git a/graphql/schema/testdata/apolloservice/output/auth-directive.graphql b/graphql/schema/testdata/apolloservice/output/auth-directive.graphql index d11d8dd6f8b..21d52d8d9b6 100644 --- a/graphql/schema/testdata/apolloservice/output/auth-directive.graphql +++ b/graphql/schema/testdata/apolloservice/output/auth-directive.graphql @@ -191,6 +191,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/apolloservice/output/custom-directive.graphql b/graphql/schema/testdata/apolloservice/output/custom-directive.graphql index 0ffe521b151..faee5eaf61d 100644 --- a/graphql/schema/testdata/apolloservice/output/custom-directive.graphql +++ b/graphql/schema/testdata/apolloservice/output/custom-directive.graphql @@ -183,6 +183,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/apolloservice/output/extended-types.graphql b/graphql/schema/testdata/apolloservice/output/extended-types.graphql index 4c2a6ab110b..b7a32569364 100644 --- a/graphql/schema/testdata/apolloservice/output/extended-types.graphql +++ b/graphql/schema/testdata/apolloservice/output/extended-types.graphql @@ -197,6 +197,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/apolloservice/output/generate-directive.graphql b/graphql/schema/testdata/apolloservice/output/generate-directive.graphql index fd38dab07b9..6079d174dd3 100644 --- a/graphql/schema/testdata/apolloservice/output/generate-directive.graphql +++ b/graphql/schema/testdata/apolloservice/output/generate-directive.graphql @@ -193,6 +193,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/apolloservice/output/single-extended-type.graphql b/graphql/schema/testdata/apolloservice/output/single-extended-type.graphql index 94acbbcc7a3..d89b66ba2cd 100644 --- a/graphql/schema/testdata/apolloservice/output/single-extended-type.graphql +++ b/graphql/schema/testdata/apolloservice/output/single-extended-type.graphql @@ -178,6 +178,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/apollo-federation.graphql b/graphql/schema/testdata/schemagen/output/apollo-federation.graphql index 6e2ce105791..d9cfdb3a3d6 100644 --- a/graphql/schema/testdata/schemagen/output/apollo-federation.graphql +++ b/graphql/schema/testdata/schemagen/output/apollo-federation.graphql @@ -213,6 +213,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/auth-on-interfaces.graphql b/graphql/schema/testdata/schemagen/output/auth-on-interfaces.graphql index ea87104b74f..0d04be6138d 100644 --- a/graphql/schema/testdata/schemagen/output/auth-on-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/auth-on-interfaces.graphql @@ -195,6 +195,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/authorization.graphql b/graphql/schema/testdata/schemagen/output/authorization.graphql index b04bf479f80..2d8fc5fdd5f 100644 --- a/graphql/schema/testdata/schemagen/output/authorization.graphql +++ b/graphql/schema/testdata/schemagen/output/authorization.graphql @@ -191,6 +191,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql b/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql index cf11ecc3856..0ca61e96780 100755 --- a/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql +++ b/graphql/schema/testdata/schemagen/output/comments-and-descriptions.graphql @@ -204,6 +204,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-dql-query-with-subscription.graphql b/graphql/schema/testdata/schemagen/output/custom-dql-query-with-subscription.graphql index 99d4d850e10..1a62284955d 100755 --- a/graphql/schema/testdata/schemagen/output/custom-dql-query-with-subscription.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-dql-query-with-subscription.graphql @@ -192,6 +192,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-mutation.graphql b/graphql/schema/testdata/schemagen/output/custom-mutation.graphql index 1b48735de16..06d28ca678d 100644 --- a/graphql/schema/testdata/schemagen/output/custom-mutation.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-mutation.graphql @@ -182,6 +182,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql b/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql index 7184d90e5a8..b90a2968f9b 100755 --- a/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-nested-types.graphql @@ -199,6 +199,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql b/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql index d441721cf27..2be0c1029a5 100644 --- a/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-mixed-types.graphql @@ -183,6 +183,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql index bbc666a87e1..2bc65e9c153 100755 --- a/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-not-dgraph-type.graphql @@ -182,6 +182,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql index a38c50561d8..d9d610b6610 100755 --- a/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/custom-query-with-dgraph-type.graphql @@ -178,6 +178,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/deprecated.graphql b/graphql/schema/testdata/schemagen/output/deprecated.graphql index 52cb4ea15d4..7c8d6f31e92 100755 --- a/graphql/schema/testdata/schemagen/output/deprecated.graphql +++ b/graphql/schema/testdata/schemagen/output/deprecated.graphql @@ -178,6 +178,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql index b1af0955121..954aee7c876 100755 --- a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-on-concrete-type-with-interfaces.graphql @@ -195,6 +195,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql index 44da4eec782..1c001e3ba2b 100755 --- a/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/dgraph-reverse-directive-with-interfaces.graphql @@ -195,6 +195,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql b/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql index c352bb70d87..beecdfa3148 100755 --- a/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/field-with-id-directive.graphql @@ -192,6 +192,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/field-with-multiple-@id-fields.graphql b/graphql/schema/testdata/schemagen/output/field-with-multiple-@id-fields.graphql index 13aa2507611..c900da9a382 100755 --- a/graphql/schema/testdata/schemagen/output/field-with-multiple-@id-fields.graphql +++ b/graphql/schema/testdata/schemagen/output/field-with-multiple-@id-fields.graphql @@ -192,6 +192,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql b/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql index f2145184ee6..df233160251 100755 --- a/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/field-with-reverse-predicate-in-dgraph-directive.graphql @@ -187,6 +187,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql index 64d88e15dd9..3edc81e66a8 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-all-empty.graphql @@ -190,6 +190,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql index fd2ae029d78..cb02a65c8c8 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-circular.graphql @@ -194,6 +194,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql index 480d42cc906..ff7aa950e48 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-custom-mutation.graphql @@ -182,6 +182,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql index ce22f674d5a..dc802d622d7 100644 --- a/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql +++ b/graphql/schema/testdata/schemagen/output/filter-cleanSchema-directLink.graphql @@ -192,6 +192,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/generate-directive.graphql b/graphql/schema/testdata/schemagen/output/generate-directive.graphql index 046c376fd08..46ebace514f 100644 --- a/graphql/schema/testdata/schemagen/output/generate-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/generate-directive.graphql @@ -193,6 +193,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/geo-type.graphql b/graphql/schema/testdata/schemagen/output/geo-type.graphql index 7b007dbea08..de3e69e8f80 100644 --- a/graphql/schema/testdata/schemagen/output/geo-type.graphql +++ b/graphql/schema/testdata/schemagen/output/geo-type.graphql @@ -184,6 +184,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql index 2a6e74d672c..3a0e3c1dcff 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface-having-directive.graphql @@ -203,6 +203,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql index 7262833b462..4fecdc70a88 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-interface.graphql @@ -205,6 +205,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql b/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql index 2a6e74d672c..3a0e3c1dcff 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse-with-type-having-directive.graphql @@ -203,6 +203,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse.graphql b/graphql/schema/testdata/schemagen/output/hasInverse.graphql index e550998e55a..7085dc1c44f 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse.graphql @@ -184,6 +184,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql b/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql index 08cebd56299..c5366c0976f 100755 --- a/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql +++ b/graphql/schema/testdata/schemagen/output/hasInverse_withSubscription.graphql @@ -184,6 +184,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/hasfilter.graphql b/graphql/schema/testdata/schemagen/output/hasfilter.graphql index e5adcc1acc6..74c1a475b4b 100644 --- a/graphql/schema/testdata/schemagen/output/hasfilter.graphql +++ b/graphql/schema/testdata/schemagen/output/hasfilter.graphql @@ -186,6 +186,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql b/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql index 0d50f4fcb38..df3262368c0 100755 --- a/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/ignore-unsupported-directive.graphql @@ -185,6 +185,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql b/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql index a604dd070c5..a915812c3a7 100644 --- a/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-dgraph-pred.graphql @@ -194,6 +194,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql b/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql index b69bab2269d..eb2d4b277a8 100755 --- a/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-id-directive.graphql @@ -190,6 +190,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql b/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql index 90161b27860..a49d47feefd 100755 --- a/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql +++ b/graphql/schema/testdata/schemagen/output/interface-with-no-ids.graphql @@ -188,6 +188,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql b/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql index 2314846daa9..a6df4ec85bb 100755 --- a/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql +++ b/graphql/schema/testdata/schemagen/output/interfaces-with-types-and-password.graphql @@ -213,6 +213,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql b/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql index 53da87263b2..bed253f757d 100755 --- a/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql +++ b/graphql/schema/testdata/schemagen/output/interfaces-with-types.graphql @@ -213,6 +213,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/lambda-directive.graphql b/graphql/schema/testdata/schemagen/output/lambda-directive.graphql index 8df251f64a7..e7d78020a6e 100644 --- a/graphql/schema/testdata/schemagen/output/lambda-directive.graphql +++ b/graphql/schema/testdata/schemagen/output/lambda-directive.graphql @@ -180,6 +180,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/language-tags.graphql b/graphql/schema/testdata/schemagen/output/language-tags.graphql index 75d0f6daa9a..a8d49f7089c 100755 --- a/graphql/schema/testdata/schemagen/output/language-tags.graphql +++ b/graphql/schema/testdata/schemagen/output/language-tags.graphql @@ -193,6 +193,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql b/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql index 5430dbf9e17..056eb595595 100755 --- a/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql +++ b/graphql/schema/testdata/schemagen/output/no-id-field-with-searchables.graphql @@ -177,6 +177,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/no-id-field.graphql b/graphql/schema/testdata/schemagen/output/no-id-field.graphql index 1976d50b845..fbd3b6e9961 100755 --- a/graphql/schema/testdata/schemagen/output/no-id-field.graphql +++ b/graphql/schema/testdata/schemagen/output/no-id-field.graphql @@ -190,6 +190,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/password-type.graphql b/graphql/schema/testdata/schemagen/output/password-type.graphql index 7bfe0bf4007..50fd9a43acc 100755 --- a/graphql/schema/testdata/schemagen/output/password-type.graphql +++ b/graphql/schema/testdata/schemagen/output/password-type.graphql @@ -178,6 +178,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/random.graphql b/graphql/schema/testdata/schemagen/output/random.graphql index 117b334faef..1883253acc9 100644 --- a/graphql/schema/testdata/schemagen/output/random.graphql +++ b/graphql/schema/testdata/schemagen/output/random.graphql @@ -196,6 +196,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/searchables-references.graphql b/graphql/schema/testdata/schemagen/output/searchables-references.graphql index a1d33610f5a..16e3cb98ed6 100755 --- a/graphql/schema/testdata/schemagen/output/searchables-references.graphql +++ b/graphql/schema/testdata/schemagen/output/searchables-references.graphql @@ -188,6 +188,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/searchables.graphql b/graphql/schema/testdata/schemagen/output/searchables.graphql index 8e21af2ddcd..d0253dece91 100755 --- a/graphql/schema/testdata/schemagen/output/searchables.graphql +++ b/graphql/schema/testdata/schemagen/output/searchables.graphql @@ -208,6 +208,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql b/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql index dc67bd55967..2fa9e7f8ef7 100755 --- a/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql +++ b/graphql/schema/testdata/schemagen/output/single-type-with-enum.graphql @@ -186,6 +186,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/single-type.graphql b/graphql/schema/testdata/schemagen/output/single-type.graphql index ffd93575abf..28fae1ba7b0 100755 --- a/graphql/schema/testdata/schemagen/output/single-type.graphql +++ b/graphql/schema/testdata/schemagen/output/single-type.graphql @@ -181,6 +181,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql b/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql index b789d8551f7..a165f859edb 100755 --- a/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql +++ b/graphql/schema/testdata/schemagen/output/type-implements-multiple-interfaces.graphql @@ -195,6 +195,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-reference.graphql b/graphql/schema/testdata/schemagen/output/type-reference.graphql index 721497a18fd..e12d8a7300f 100755 --- a/graphql/schema/testdata/schemagen/output/type-reference.graphql +++ b/graphql/schema/testdata/schemagen/output/type-reference.graphql @@ -185,6 +185,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql b/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql index 192482c12fa..7dbc6dd73fc 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-arguments-on-field.graphql @@ -186,6 +186,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql b/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql index 7e4c71914f7..b9ed4f1e665 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-custom-field-on-dgraph-type.graphql @@ -185,6 +185,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql b/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql index e85ea68b041..463404f5488 100644 --- a/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql +++ b/graphql/schema/testdata/schemagen/output/type-with-custom-fields-on-remote-type.graphql @@ -185,6 +185,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql b/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql index ff78a20fbb1..ae5bc26ca2f 100644 --- a/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql +++ b/graphql/schema/testdata/schemagen/output/type-without-orderables.graphql @@ -180,6 +180,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/testdata/schemagen/output/union.graphql b/graphql/schema/testdata/schemagen/output/union.graphql index 33eaa4c6c54..7155d1324d0 100644 --- a/graphql/schema/testdata/schemagen/output/union.graphql +++ b/graphql/schema/testdata/schemagen/output/union.graphql @@ -227,6 +227,7 @@ input GenerateMutationParams { directive @hasInverse(field: String!) on FIELD_DEFINITION directive @search(by: [DgraphIndex!]) on FIELD_DEFINITION +directive @hm_embedding on FIELD_DEFINITION directive @dgraph(type: String, pred: String) on OBJECT | INTERFACE | FIELD_DEFINITION directive @id(interface: Boolean) on FIELD_DEFINITION directive @withSubscription on OBJECT | INTERFACE | FIELD_DEFINITION diff --git a/graphql/schema/wrappers.go b/graphql/schema/wrappers.go index 40239982a55..95fa27c5fa5 100644 --- a/graphql/schema/wrappers.go +++ b/graphql/schema/wrappers.go @@ -85,24 +85,35 @@ type EntityRepresentations struct { // Query/Mutation types and arg names const ( - GetQuery QueryType = "get" - FilterQuery QueryType = "query" - AggregateQuery QueryType = "aggregate" - SchemaQuery QueryType = "schema" - EntitiesQuery QueryType = "entities" - PasswordQuery QueryType = "checkPassword" - HTTPQuery QueryType = "http" - DQLQuery QueryType = "dql" - NotSupportedQuery QueryType = "notsupported" - AddMutation MutationType = "add" - UpdateMutation MutationType = "update" - DeleteMutation MutationType = "delete" - HTTPMutation MutationType = "http" - NotSupportedMutation MutationType = "notsupported" - IDType = "ID" - InputArgName = "input" - UpsertArgName = "upsert" - FilterArgName = "filter" + GetQuery QueryType = "get" + SimilarByIdQuery QueryType = "querySimilarById" + SimilarByEmbeddingQuery QueryType = "querySimilarByEmbedding" + FilterQuery QueryType = "query" + AggregateQuery QueryType = "aggregate" + SchemaQuery QueryType = "schema" + EntitiesQuery QueryType = "entities" + PasswordQuery QueryType = "checkPassword" + HTTPQuery QueryType = "http" + DQLQuery QueryType = "dql" + NotSupportedQuery QueryType = "notsupported" + AddMutation MutationType = "add" + UpdateMutation MutationType = "update" + DeleteMutation MutationType = "delete" + HTTPMutation MutationType = "http" + NotSupportedMutation MutationType = "notsupported" + IDType = "ID" + InputArgName = "input" + UpsertArgName = "upsert" + FilterArgName = "filter" + SimilarByArgName = "by" + SimilarTopKArgName = "topK" + SimilarVectorArgName = "vector" + EmbeddingEnumSuffix = "Embedding" + SimilarQueryPrefix = "querySimilar" + SimilarByIdQuerySuffix = "ById" + SimilarByEmbeddingQuerySuffix = "ByEmbedding" + SimilarQueryResultTypeSuffix = "WithDistance" + SimilarQueryDistanceFieldName = "hm_distance" ) // Schema represents a valid GraphQL schema @@ -269,6 +280,7 @@ type FieldDefinition interface { IsID() bool IsExternal() bool HasIDDirective() bool + HasEmbeddingDirective() bool HasInterfaceArg() bool Inverse() FieldDefinition WithMemberType(string) FieldDefinition @@ -1376,8 +1388,11 @@ func (f *field) IDArgValue() (xids map[string]string, uid uint64, err error) { // or Password. Therefore the non ID and Password field is an XID. // TODO maybe there is a better way to do this. for _, arg := range f.field.Arguments { + xidArgName = "" if (idField == nil || arg.Name != idField.Name()) && - (passwordField == nil || arg.Name != passwordField.Name()) { + (passwordField == nil || arg.Name != passwordField.Name()) && + (queryType(f.field.Name, nil) != SimilarByIdQuery || + (arg.Name != SimilarTopKArgName && arg.Name != SimilarByArgName)) { xidArgName = arg.Name } @@ -2007,6 +2022,10 @@ func queryType(name string, custom *ast.Directive) QueryType { return GetQuery case name == "__schema" || name == "__type" || name == "__typename": return SchemaQuery + case strings.HasPrefix(name, SimilarQueryPrefix) && strings.HasSuffix(name, SimilarByIdQuerySuffix): + return SimilarByIdQuery + case strings.HasPrefix(name, SimilarQueryPrefix) && strings.HasSuffix(name, SimilarByEmbeddingQuerySuffix): + return SimilarByEmbeddingQuery case strings.HasPrefix(name, "query"): return FilterQuery case strings.HasPrefix(name, "check"): @@ -2325,6 +2344,18 @@ func hasIDDirective(fd *ast.FieldDefinition) bool { return id != nil } +func (fd *fieldDefinition) HasEmbeddingDirective() bool { + if fd.fieldDef == nil { + return false + } + return hasEmbeddingDirective(fd.fieldDef) +} + +func hasEmbeddingDirective(fd *ast.FieldDefinition) bool { + id := fd.Directives.ForName(embeddingDirective) + return id != nil +} + func (fd *fieldDefinition) HasInterfaceArg() bool { if fd.fieldDef == nil { return false diff --git a/query/outputnode.go b/query/outputnode.go index 9351ce01d9c..6755eff81fc 100644 --- a/query/outputnode.go +++ b/query/outputnode.go @@ -481,6 +481,18 @@ func (enc *encoder) AddValue(fj fastJsonNode, attr uint16, v types.Val) error { } func (enc *encoder) AddListValue(fj fastJsonNode, attr uint16, v types.Val, list bool) error { + if v.Tid == types.VFloatID { + for _, f := range v.Value.([]float64) { + bs := []byte(strconv.FormatFloat(f, 'E', -1, 64)) + sn, err := enc.makeScalarNode(attr, bs, true) + if err != nil { + return err + } + + enc.addChildren(fj, sn) + } + return nil + } bs, err := valToBytes(v) if err != nil { return nil // Ignore this. @@ -1562,7 +1574,7 @@ func (sg *SubGraph) preTraverse(enc *encoder, uid uint64, dst fastJsonNode) erro if lang != "" && lang != "*" { fieldNameWithTag += "@" + lang } - encodeAsList := pc.List && lang == "" + encodeAsList := (pc.List && lang == "") if err := enc.AddListValue(dst, enc.idForAttr(fieldNameWithTag), sv, encodeAsList); err != nil { return err diff --git a/query/query.go b/query/query.go index 5c728895f4f..4cc531bb382 100644 --- a/query/query.go +++ b/query/query.go @@ -1176,6 +1176,12 @@ func (sg *SubGraph) transformVars(doneVars map[string]varValue, path []*SubGraph mt.Const = val continue } + // TODO: Need to understand why certain aggregations map to uid = 0 + // while others map to uid = MaxUint64 + if val, ok := newMap[0]; ok && len(newMap) == 1 { + mt.Const = val + continue + } mt.Val = newMap } @@ -1258,8 +1264,10 @@ func (sg *SubGraph) valueVarAggregation(doneVars map[string]varValue, path []*Su } if rangeOver == nil { it := doneVars[sg.Params.Var] + mp[0] = sg.MathExp.Const it.Vals = mp doneVars[sg.Params.Var] = it + sg.Params.UidToVal = mp return nil } for _, uid := range rangeOver.Uids {