Spaces:
Running
Running
| // _ _ | |
| // __ _____ __ ___ ___ __ _| |_ ___ | |
| // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ | |
| // \ V V / __/ (_| |\ V /| | (_| | || __/ | |
| // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| | |
| // | |
| // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. | |
| // | |
| // CONTACT: [email protected] | |
| // | |
| package objects | |
| import ( | |
| "context" | |
| "fmt" | |
| "net/http" | |
| "github.com/go-openapi/strfmt" | |
| "github.com/pkg/errors" | |
| "github.com/sirupsen/logrus" | |
| "github.com/stretchr/testify/mock" | |
| "github.com/tailor-inc/graphql" | |
| "github.com/tailor-inc/graphql/language/ast" | |
| "github.com/weaviate/weaviate/adapters/handlers/graphql/descriptions" | |
| "github.com/weaviate/weaviate/entities/additional" | |
| "github.com/weaviate/weaviate/entities/filters" | |
| "github.com/weaviate/weaviate/entities/models" | |
| "github.com/weaviate/weaviate/entities/modulecapabilities" | |
| "github.com/weaviate/weaviate/entities/moduletools" | |
| "github.com/weaviate/weaviate/entities/schema" | |
| "github.com/weaviate/weaviate/entities/schema/crossref" | |
| "github.com/weaviate/weaviate/entities/search" | |
| "github.com/weaviate/weaviate/entities/vectorindex/hnsw" | |
| ) | |
| const FindObjectFn = "func(context.Context, string, strfmt.UUID, " + | |
| "search.SelectProperties, additional.Properties, string) (*search.Result, error)" | |
| type fakeSchemaManager struct { | |
| CalledWith struct { | |
| fromClass string | |
| property string | |
| toClass string | |
| } | |
| GetSchemaResponse schema.Schema | |
| GetschemaErr error | |
| } | |
| func (f *fakeSchemaManager) UpdatePropertyAddDataType(ctx context.Context, principal *models.Principal, | |
| fromClass, property, toClass string, | |
| ) error { | |
| f.CalledWith = struct { | |
| fromClass string | |
| property string | |
| toClass string | |
| }{ | |
| fromClass: fromClass, | |
| property: property, | |
| toClass: toClass, | |
| } | |
| return nil | |
| } | |
| func (f *fakeSchemaManager) GetSchema(principal *models.Principal) (schema.Schema, error) { | |
| return f.GetSchemaResponse, f.GetschemaErr | |
| } | |
| func (f *fakeSchemaManager) ShardOwner(class, shard string) (string, error) { return "", nil } | |
| func (f *fakeSchemaManager) TenantShard(class, tenant string) string { return tenant } | |
| func (f *fakeSchemaManager) ShardFromUUID(class string, uuid []byte) string { return "" } | |
| func (f *fakeSchemaManager) GetClass(ctx context.Context, principal *models.Principal, | |
| name string, | |
| ) (*models.Class, error) { | |
| classes := f.GetSchemaResponse.Objects.Classes | |
| for _, class := range classes { | |
| if class.Class == name { | |
| return class, f.GetschemaErr | |
| } | |
| } | |
| return nil, f.GetschemaErr | |
| } | |
| func (f *fakeSchemaManager) AddClass(ctx context.Context, principal *models.Principal, | |
| class *models.Class, | |
| ) error { | |
| if f.GetSchemaResponse.Objects == nil { | |
| f.GetSchemaResponse.Objects = schema.Empty().Objects | |
| } | |
| class.VectorIndexConfig = hnsw.UserConfig{} | |
| class.VectorIndexType = "hnsw" | |
| class.Vectorizer = "none" | |
| classes := f.GetSchemaResponse.Objects.Classes | |
| if classes != nil { | |
| classes = append(classes, class) | |
| } else { | |
| classes = []*models.Class{class} | |
| } | |
| f.GetSchemaResponse.Objects.Classes = classes | |
| return nil | |
| } | |
| func (f *fakeSchemaManager) AddClassProperty(ctx context.Context, principal *models.Principal, | |
| class string, property *models.Property, | |
| ) error { | |
| classes := f.GetSchemaResponse.Objects.Classes | |
| for _, c := range classes { | |
| if c.Class == class { | |
| props := c.Properties | |
| if props != nil { | |
| props = append(props, property) | |
| } else { | |
| props = []*models.Property{property} | |
| } | |
| c.Properties = props | |
| break | |
| } | |
| } | |
| return nil | |
| } | |
| func (f *fakeSchemaManager) MergeClassObjectProperty(ctx context.Context, principal *models.Principal, | |
| class string, property *models.Property, | |
| ) error { | |
| classes := f.GetSchemaResponse.Objects.Classes | |
| for _, c := range classes { | |
| if c.Class == class { | |
| for i, prop := range c.Properties { | |
| if prop.Name == property.Name { | |
| c.Properties[i].NestedProperties, _ = schema.MergeRecursivelyNestedProperties( | |
| c.Properties[i].NestedProperties, property.NestedProperties) | |
| break | |
| } | |
| } | |
| break | |
| } | |
| } | |
| return nil | |
| } | |
| type fakeLocks struct { | |
| Err error | |
| } | |
| func (f *fakeLocks) LockConnector() (func() error, error) { | |
| return func() error { return nil }, f.Err | |
| } | |
| func (f *fakeLocks) LockSchema() (func() error, error) { | |
| return func() error { return nil }, f.Err | |
| } | |
| type fakeAuthorizer struct { | |
| Err error | |
| } | |
| func (f *fakeAuthorizer) Authorize(principal *models.Principal, verb, resource string) error { | |
| return f.Err | |
| } | |
| type fakeVectorRepo struct { | |
| mock.Mock | |
| } | |
| func (f *fakeVectorRepo) Exists(ctx context.Context, class string, id strfmt.UUID, repl *additional.ReplicationProperties, tenant string) (bool, error) { | |
| args := f.Called(class, id) | |
| return args.Bool(0), args.Error(1) | |
| } | |
| func (f *fakeVectorRepo) Object(ctx context.Context, cls string, id strfmt.UUID, | |
| props search.SelectProperties, additional additional.Properties, | |
| repl *additional.ReplicationProperties, tenant string, | |
| ) (*search.Result, error) { | |
| args := f.Called(cls, id, props, additional, tenant) | |
| if args.Get(0) != nil { | |
| return args.Get(0).(*search.Result), args.Error(1) | |
| } | |
| return nil, args.Error(1) | |
| } | |
| func (f *fakeVectorRepo) ObjectByID(ctx context.Context, id strfmt.UUID, | |
| props search.SelectProperties, additional additional.Properties, | |
| tenant string, | |
| ) (*search.Result, error) { | |
| args := f.Called(id, props, additional) | |
| if args.Get(0) != nil { | |
| return args.Get(0).(*search.Result), args.Error(1) | |
| } | |
| return nil, args.Error(1) | |
| } | |
| func (f *fakeVectorRepo) ObjectSearch(ctx context.Context, offset, limit int, filters *filters.LocalFilter, | |
| sort []filters.Sort, additional additional.Properties, tenant string, | |
| ) (search.Results, error) { | |
| args := f.Called(offset, limit, sort, filters, additional) | |
| return args.Get(0).([]search.Result), args.Error(1) | |
| } | |
| func (f *fakeVectorRepo) Query(ctx context.Context, q *QueryInput) (search.Results, *Error) { | |
| args := f.Called(q) | |
| res, err := args.Get(0).([]search.Result), args.Error(1).(*Error) | |
| return res, err | |
| } | |
| func (f *fakeVectorRepo) PutObject(ctx context.Context, concept *models.Object, vector []float32, | |
| repl *additional.ReplicationProperties, | |
| ) error { | |
| args := f.Called(concept, vector) | |
| return args.Error(0) | |
| } | |
| func (f *fakeVectorRepo) BatchPutObjects(ctx context.Context, batch BatchObjects, | |
| repl *additional.ReplicationProperties, | |
| ) (BatchObjects, error) { | |
| args := f.Called(batch) | |
| return batch, args.Error(0) | |
| } | |
| func (f *fakeVectorRepo) AddBatchReferences(ctx context.Context, batch BatchReferences, | |
| repl *additional.ReplicationProperties, | |
| ) (BatchReferences, error) { | |
| args := f.Called(batch) | |
| return batch, args.Error(0) | |
| } | |
| func (f *fakeVectorRepo) BatchDeleteObjects(ctx context.Context, params BatchDeleteParams, | |
| repl *additional.ReplicationProperties, tenant string, | |
| ) (BatchDeleteResult, error) { | |
| args := f.Called(params) | |
| return args.Get(0).(BatchDeleteResult), args.Error(1) | |
| } | |
| func (f *fakeVectorRepo) Merge(ctx context.Context, merge MergeDocument, repl *additional.ReplicationProperties, tenant string) error { | |
| args := f.Called(merge) | |
| return args.Error(0) | |
| } | |
| func (f *fakeVectorRepo) DeleteObject(ctx context.Context, className string, | |
| id strfmt.UUID, repl *additional.ReplicationProperties, tenant string, | |
| ) error { | |
| args := f.Called(className, id) | |
| return args.Error(0) | |
| } | |
| func (f *fakeVectorRepo) AddReference(ctx context.Context, source *crossref.RefSource, | |
| target *crossref.Ref, repl *additional.ReplicationProperties, tenant string, | |
| ) error { | |
| args := f.Called(source, target) | |
| return args.Error(0) | |
| } | |
| func (f *fakeVectorRepo) ReferenceVectorSearch(ctx context.Context, | |
| obj *models.Object, refProps map[string]struct{}, | |
| ) ([][]float32, error) { | |
| return nil, nil | |
| } | |
| type fakeExtender struct { | |
| multi []search.Result | |
| } | |
| func (f *fakeExtender) AdditionalPropertyFn(ctx context.Context, | |
| in []search.Result, params interface{}, limit *int, | |
| argumentModuleParams map[string]interface{}, cfg moduletools.ClassConfig, | |
| ) ([]search.Result, error) { | |
| return f.multi, nil | |
| } | |
| func (f *fakeExtender) ExtractAdditionalFn(param []*ast.Argument) interface{} { | |
| return nil | |
| } | |
| func (f *fakeExtender) AdditionalPropertyDefaultValue() interface{} { | |
| return getDefaultParam("nearestNeighbors") | |
| } | |
| type fakeProjector struct { | |
| multi []search.Result | |
| } | |
| func (f *fakeProjector) AdditionalPropertyFn(ctx context.Context, | |
| in []search.Result, params interface{}, limit *int, | |
| argumentModuleParams map[string]interface{}, cfg moduletools.ClassConfig, | |
| ) ([]search.Result, error) { | |
| return f.multi, nil | |
| } | |
| func (f *fakeProjector) ExtractAdditionalFn(param []*ast.Argument) interface{} { | |
| return nil | |
| } | |
| func (f *fakeProjector) AdditionalPropertyDefaultValue() interface{} { | |
| return getDefaultParam("featureProjection") | |
| } | |
| type fakePathBuilder struct { | |
| multi []search.Result | |
| } | |
| func (f *fakePathBuilder) AdditionalPropertyFn(ctx context.Context, | |
| in []search.Result, params interface{}, limit *int, | |
| argumentModuleParams map[string]interface{}, cfg moduletools.ClassConfig, | |
| ) ([]search.Result, error) { | |
| return f.multi, nil | |
| } | |
| func (f *fakePathBuilder) ExtractAdditionalFn(param []*ast.Argument) interface{} { | |
| return nil | |
| } | |
| func (f *fakePathBuilder) AdditionalPropertyDefaultValue() interface{} { | |
| return getDefaultParam("semanticPath") | |
| } | |
| type fakeModulesProvider struct { | |
| mock.Mock | |
| customExtender *fakeExtender | |
| customProjector *fakeProjector | |
| } | |
| func (p *fakeModulesProvider) GetObjectAdditionalExtend(ctx context.Context, | |
| in *search.Result, moduleParams map[string]interface{}, | |
| ) (*search.Result, error) { | |
| res, err := p.additionalExtend(ctx, search.Results{*in}, moduleParams, "ObjectGet") | |
| if err != nil { | |
| return nil, err | |
| } | |
| return &res[0], nil | |
| } | |
| func (p *fakeModulesProvider) ListObjectsAdditionalExtend(ctx context.Context, | |
| in search.Results, moduleParams map[string]interface{}, | |
| ) (search.Results, error) { | |
| return p.additionalExtend(ctx, in, moduleParams, "ObjectList") | |
| } | |
| func (p *fakeModulesProvider) UsingRef2Vec(moduleName string) bool { | |
| args := p.Called(moduleName) | |
| return args.Bool(0) | |
| } | |
| func (p *fakeModulesProvider) UpdateVector(ctx context.Context, object *models.Object, class *models.Class, | |
| objectDiff *moduletools.ObjectDiff, findObjFn modulecapabilities.FindObjectFn, logger logrus.FieldLogger, | |
| ) error { | |
| args := p.Called(object, findObjFn) | |
| switch vec := args.Get(0).(type) { | |
| case models.C11yVector: | |
| object.Vector = vec | |
| return args.Error(1) | |
| case []float32: | |
| object.Vector = vec | |
| return args.Error(1) | |
| default: | |
| return args.Error(1) | |
| } | |
| } | |
| func (p *fakeModulesProvider) VectorizerName(className string) (string, error) { | |
| args := p.Called(className) | |
| return args.String(0), args.Error(1) | |
| } | |
| func (p *fakeModulesProvider) additionalExtend(ctx context.Context, | |
| in search.Results, moduleParams map[string]interface{}, capability string, | |
| ) (search.Results, error) { | |
| txt2vec := newNearCustomTextModule(p.getExtender(), p.getProjector(), &fakePathBuilder{}) | |
| additionalProperties := txt2vec.AdditionalProperties() | |
| if err := p.checkCapabilities(additionalProperties, moduleParams, capability); err != nil { | |
| return nil, err | |
| } | |
| for name, value := range moduleParams { | |
| additionalPropertyFn := p.getAdditionalPropertyFn(additionalProperties[name], capability) | |
| if additionalPropertyFn != nil && value != nil { | |
| resArray, err := additionalPropertyFn(ctx, in, nil, nil, nil, nil) | |
| if err != nil { | |
| return nil, err | |
| } | |
| in = resArray | |
| } | |
| } | |
| return in, nil | |
| } | |
| func (p *fakeModulesProvider) checkCapabilities(additionalProperties map[string]modulecapabilities.AdditionalProperty, | |
| moduleParams map[string]interface{}, capability string, | |
| ) error { | |
| for name := range moduleParams { | |
| additionalPropertyFn := p.getAdditionalPropertyFn(additionalProperties[name], capability) | |
| if additionalPropertyFn == nil { | |
| return errors.Errorf("unknown capability: %s", name) | |
| } | |
| } | |
| return nil | |
| } | |
| func (p *fakeModulesProvider) getAdditionalPropertyFn(additionalProperty modulecapabilities.AdditionalProperty, | |
| capability string, | |
| ) modulecapabilities.AdditionalPropertyFn { | |
| switch capability { | |
| case "ObjectGet": | |
| return additionalProperty.SearchFunctions.ObjectGet | |
| case "ObjectList": | |
| return additionalProperty.SearchFunctions.ObjectList | |
| case "ExploreGet": | |
| return additionalProperty.SearchFunctions.ExploreGet | |
| case "ExploreList": | |
| return additionalProperty.SearchFunctions.ExploreList | |
| default: | |
| return nil | |
| } | |
| } | |
| func (p *fakeModulesProvider) getExtender() *fakeExtender { | |
| if p.customExtender != nil { | |
| return p.customExtender | |
| } | |
| return &fakeExtender{} | |
| } | |
| func (p *fakeModulesProvider) getProjector() *fakeProjector { | |
| if p.customProjector != nil { | |
| return p.customProjector | |
| } | |
| return &fakeProjector{} | |
| } | |
| type nearCustomTextParams struct { | |
| Values []string | |
| MoveTo nearExploreMove | |
| Certainty float64 | |
| } | |
| type nearExploreMove struct { | |
| Values []string | |
| Force float32 | |
| Objects []nearObjectMove | |
| } | |
| type nearObjectMove struct { | |
| ID string | |
| Beacon string | |
| } | |
| type nearCustomTextModule struct { | |
| fakeExtender *fakeExtender | |
| fakeProjector *fakeProjector | |
| fakePathBuilder *fakePathBuilder | |
| } | |
| func newNearCustomTextModule( | |
| fakeExtender *fakeExtender, | |
| fakeProjector *fakeProjector, | |
| fakePathBuilder *fakePathBuilder, | |
| ) *nearCustomTextModule { | |
| return &nearCustomTextModule{fakeExtender, fakeProjector, fakePathBuilder} | |
| } | |
| func (m *nearCustomTextModule) Name() string { | |
| return "mock-custom-near-text-module" | |
| } | |
| func (m *nearCustomTextModule) Init(params moduletools.ModuleInitParams) error { | |
| return nil | |
| } | |
| func (m *nearCustomTextModule) RootHandler() http.Handler { | |
| return nil | |
| } | |
| func (m *nearCustomTextModule) getNearCustomTextArgument(classname string) *graphql.ArgumentConfig { | |
| prefix := classname | |
| return &graphql.ArgumentConfig{ | |
| Type: graphql.NewInputObject( | |
| graphql.InputObjectConfig{ | |
| Name: fmt.Sprintf("%sNearCustomTextInpObj", prefix), | |
| Fields: graphql.InputObjectConfigFieldMap{ | |
| "concepts": &graphql.InputObjectFieldConfig{ | |
| Type: graphql.NewNonNull(graphql.NewList(graphql.String)), | |
| }, | |
| "moveTo": &graphql.InputObjectFieldConfig{ | |
| Description: descriptions.VectorMovement, | |
| Type: graphql.NewInputObject( | |
| graphql.InputObjectConfig{ | |
| Name: fmt.Sprintf("%sMoveTo", prefix), | |
| Fields: graphql.InputObjectConfigFieldMap{ | |
| "concepts": &graphql.InputObjectFieldConfig{ | |
| Description: descriptions.Keywords, | |
| Type: graphql.NewList(graphql.String), | |
| }, | |
| "objects": &graphql.InputObjectFieldConfig{ | |
| Description: "objects", | |
| Type: graphql.NewList(graphql.NewInputObject( | |
| graphql.InputObjectConfig{ | |
| Name: fmt.Sprintf("%sMovementObjectsInpObj", prefix), | |
| Fields: graphql.InputObjectConfigFieldMap{ | |
| "id": &graphql.InputObjectFieldConfig{ | |
| Type: graphql.String, | |
| Description: "id of an object", | |
| }, | |
| "beacon": &graphql.InputObjectFieldConfig{ | |
| Type: graphql.String, | |
| Description: descriptions.Beacon, | |
| }, | |
| }, | |
| Description: "Movement Object", | |
| }, | |
| )), | |
| }, | |
| "force": &graphql.InputObjectFieldConfig{ | |
| Description: descriptions.Force, | |
| Type: graphql.NewNonNull(graphql.Float), | |
| }, | |
| }, | |
| }), | |
| }, | |
| "certainty": &graphql.InputObjectFieldConfig{ | |
| Description: descriptions.Certainty, | |
| Type: graphql.Float, | |
| }, | |
| }, | |
| Description: descriptions.GetWhereInpObj, | |
| }, | |
| ), | |
| } | |
| } | |
| func (m *nearCustomTextModule) extractNearCustomTextArgument(source map[string]interface{}) *nearCustomTextParams { | |
| var args nearCustomTextParams | |
| concepts := source["concepts"].([]interface{}) | |
| args.Values = make([]string, len(concepts)) | |
| for i, value := range concepts { | |
| args.Values[i] = value.(string) | |
| } | |
| certainty, ok := source["certainty"] | |
| if ok { | |
| args.Certainty = certainty.(float64) | |
| } | |
| // moveTo is an optional arg, so it could be nil | |
| moveTo, ok := source["moveTo"] | |
| if ok { | |
| moveToMap := moveTo.(map[string]interface{}) | |
| res := nearExploreMove{} | |
| res.Force = float32(moveToMap["force"].(float64)) | |
| concepts, ok := moveToMap["concepts"].([]interface{}) | |
| if ok { | |
| res.Values = make([]string, len(concepts)) | |
| for i, value := range concepts { | |
| res.Values[i] = value.(string) | |
| } | |
| } | |
| objects, ok := moveToMap["objects"].([]interface{}) | |
| if ok { | |
| res.Objects = make([]nearObjectMove, len(objects)) | |
| for i, value := range objects { | |
| v, ok := value.(map[string]interface{}) | |
| if ok { | |
| if v["id"] != nil { | |
| res.Objects[i].ID = v["id"].(string) | |
| } | |
| if v["beacon"] != nil { | |
| res.Objects[i].Beacon = v["beacon"].(string) | |
| } | |
| } | |
| } | |
| } | |
| args.MoveTo = res | |
| } | |
| return &args | |
| } | |
| func (m *nearCustomTextModule) Arguments() map[string]modulecapabilities.GraphQLArgument { | |
| arguments := map[string]modulecapabilities.GraphQLArgument{} | |
| // define nearCustomText argument | |
| arguments["nearCustomText"] = modulecapabilities.GraphQLArgument{ | |
| GetArgumentsFunction: func(classname string) *graphql.ArgumentConfig { | |
| return m.getNearCustomTextArgument(classname) | |
| }, | |
| ExtractFunction: func(source map[string]interface{}) interface{} { | |
| return m.extractNearCustomTextArgument(source) | |
| }, | |
| ValidateFunction: func(param interface{}) error { | |
| // all is valid | |
| return nil | |
| }, | |
| } | |
| return arguments | |
| } | |
| // additional properties | |
| func (m *nearCustomTextModule) AdditionalProperties() map[string]modulecapabilities.AdditionalProperty { | |
| additionalProperties := map[string]modulecapabilities.AdditionalProperty{} | |
| additionalProperties["featureProjection"] = m.getFeatureProjection() | |
| additionalProperties["nearestNeighbors"] = m.getNearestNeighbors() | |
| additionalProperties["semanticPath"] = m.getSemanticPath() | |
| return additionalProperties | |
| } | |
| func (m *nearCustomTextModule) getFeatureProjection() modulecapabilities.AdditionalProperty { | |
| return modulecapabilities.AdditionalProperty{ | |
| DefaultValue: m.fakeProjector.AdditionalPropertyDefaultValue(), | |
| GraphQLNames: []string{"featureProjection"}, | |
| GraphQLFieldFunction: func(classname string) *graphql.Field { | |
| return &graphql.Field{ | |
| Args: graphql.FieldConfigArgument{ | |
| "algorithm": &graphql.ArgumentConfig{ | |
| Type: graphql.String, | |
| DefaultValue: nil, | |
| }, | |
| "dimensions": &graphql.ArgumentConfig{ | |
| Type: graphql.Int, | |
| DefaultValue: nil, | |
| }, | |
| "learningRate": &graphql.ArgumentConfig{ | |
| Type: graphql.Int, | |
| DefaultValue: nil, | |
| }, | |
| "iterations": &graphql.ArgumentConfig{ | |
| Type: graphql.Int, | |
| DefaultValue: nil, | |
| }, | |
| "perplexity": &graphql.ArgumentConfig{ | |
| Type: graphql.Int, | |
| DefaultValue: nil, | |
| }, | |
| }, | |
| Type: graphql.NewObject(graphql.ObjectConfig{ | |
| Name: fmt.Sprintf("%sAdditionalFeatureProjection", classname), | |
| Fields: graphql.Fields{ | |
| "vector": &graphql.Field{Type: graphql.NewList(graphql.Float)}, | |
| }, | |
| }), | |
| } | |
| }, | |
| GraphQLExtractFunction: m.fakeProjector.ExtractAdditionalFn, | |
| SearchFunctions: modulecapabilities.AdditionalSearch{ | |
| ObjectList: m.fakeProjector.AdditionalPropertyFn, | |
| ExploreGet: m.fakeProjector.AdditionalPropertyFn, | |
| ExploreList: m.fakeProjector.AdditionalPropertyFn, | |
| }, | |
| } | |
| } | |
| func (m *nearCustomTextModule) getNearestNeighbors() modulecapabilities.AdditionalProperty { | |
| return modulecapabilities.AdditionalProperty{ | |
| DefaultValue: m.fakeExtender.AdditionalPropertyDefaultValue(), | |
| GraphQLNames: []string{"nearestNeighbors"}, | |
| GraphQLFieldFunction: func(classname string) *graphql.Field { | |
| return &graphql.Field{ | |
| Type: graphql.NewObject(graphql.ObjectConfig{ | |
| Name: fmt.Sprintf("%sAdditionalNearestNeighbors", classname), | |
| Fields: graphql.Fields{ | |
| "neighbors": &graphql.Field{Type: graphql.NewList(graphql.NewObject(graphql.ObjectConfig{ | |
| Name: fmt.Sprintf("%sAdditionalNearestNeighborsNeighbors", classname), | |
| Fields: graphql.Fields{ | |
| "concept": &graphql.Field{Type: graphql.String}, | |
| "distance": &graphql.Field{Type: graphql.Float}, | |
| }, | |
| }))}, | |
| }, | |
| }), | |
| } | |
| }, | |
| GraphQLExtractFunction: m.fakeExtender.ExtractAdditionalFn, | |
| SearchFunctions: modulecapabilities.AdditionalSearch{ | |
| ObjectGet: m.fakeExtender.AdditionalPropertyFn, | |
| ObjectList: m.fakeExtender.AdditionalPropertyFn, | |
| ExploreGet: m.fakeExtender.AdditionalPropertyFn, | |
| ExploreList: m.fakeExtender.AdditionalPropertyFn, | |
| }, | |
| } | |
| } | |
| func (m *nearCustomTextModule) getSemanticPath() modulecapabilities.AdditionalProperty { | |
| return modulecapabilities.AdditionalProperty{ | |
| DefaultValue: m.fakePathBuilder.AdditionalPropertyDefaultValue(), | |
| GraphQLNames: []string{"semanticPath"}, | |
| GraphQLFieldFunction: func(classname string) *graphql.Field { | |
| return &graphql.Field{ | |
| Type: graphql.NewObject(graphql.ObjectConfig{ | |
| Name: fmt.Sprintf("%sAdditionalSemanticPath", classname), | |
| Fields: graphql.Fields{ | |
| "path": &graphql.Field{Type: graphql.NewList(graphql.NewObject(graphql.ObjectConfig{ | |
| Name: fmt.Sprintf("%sAdditionalSemanticPathElement", classname), | |
| Fields: graphql.Fields{ | |
| "concept": &graphql.Field{Type: graphql.String}, | |
| "distanceToQuery": &graphql.Field{Type: graphql.Float}, | |
| "distanceToResult": &graphql.Field{Type: graphql.Float}, | |
| "distanceToNext": &graphql.Field{Type: graphql.Float}, | |
| "distanceToPrevious": &graphql.Field{Type: graphql.Float}, | |
| }, | |
| }))}, | |
| }, | |
| }), | |
| } | |
| }, | |
| GraphQLExtractFunction: m.fakePathBuilder.ExtractAdditionalFn, | |
| SearchFunctions: modulecapabilities.AdditionalSearch{ | |
| ExploreGet: m.fakePathBuilder.AdditionalPropertyFn, | |
| }, | |
| } | |
| } | |
| type fakeParams struct{} | |
| func getDefaultParam(name string) interface{} { | |
| switch name { | |
| case "featureProjection", "semanticPath": | |
| return &fakeParams{} | |
| case "nearestNeighbors": | |
| return true | |
| default: | |
| return nil | |
| } | |
| } | |
| func getFakeModulesProvider(opts ...func(p *fakeModulesProvider)) *fakeModulesProvider { | |
| p := &fakeModulesProvider{} | |
| p.applyOptions(opts...) | |
| return p | |
| } | |
| func (p *fakeModulesProvider) applyOptions(opts ...func(provider *fakeModulesProvider)) { | |
| for _, opt := range opts { | |
| opt(p) | |
| } | |
| } | |
| func getFakeModulesProviderWithCustomExtenders( | |
| customExtender *fakeExtender, | |
| customProjector *fakeProjector, | |
| opts ...func(provider *fakeModulesProvider), | |
| ) *fakeModulesProvider { | |
| p := &fakeModulesProvider{mock.Mock{}, customExtender, customProjector} | |
| p.applyOptions(opts...) | |
| return p | |
| } | |
| type fakeMetrics struct { | |
| // Note: only those metric functions that relate to usage-related metrics are | |
| // covered by this mock, others are empty shells | |
| mock.Mock | |
| } | |
| func (f *fakeMetrics) BatchInc() { | |
| } | |
| func (f *fakeMetrics) BatchDec() { | |
| } | |
| func (f *fakeMetrics) BatchRefInc() { | |
| } | |
| func (f *fakeMetrics) BatchRefDec() { | |
| } | |
| func (f *fakeMetrics) BatchDeleteInc() { | |
| } | |
| func (f *fakeMetrics) BatchDeleteDec() { | |
| } | |
| func (f *fakeMetrics) AddObjectInc() { | |
| } | |
| func (f *fakeMetrics) AddObjectDec() { | |
| } | |
| func (f *fakeMetrics) UpdateObjectInc() { | |
| } | |
| func (f *fakeMetrics) UpdateObjectDec() { | |
| } | |
| func (f *fakeMetrics) MergeObjectInc() { | |
| } | |
| func (f *fakeMetrics) MergeObjectDec() { | |
| } | |
| func (f *fakeMetrics) DeleteObjectInc() { | |
| } | |
| func (f *fakeMetrics) DeleteObjectDec() { | |
| } | |
| func (f *fakeMetrics) GetObjectInc() { | |
| } | |
| func (f *fakeMetrics) GetObjectDec() { | |
| } | |
| func (f *fakeMetrics) HeadObjectInc() { | |
| } | |
| func (f *fakeMetrics) HeadObjectDec() { | |
| } | |
| func (f *fakeMetrics) AddReferenceInc() { | |
| } | |
| func (f *fakeMetrics) AddReferenceDec() { | |
| } | |
| func (f *fakeMetrics) UpdateReferenceInc() { | |
| } | |
| func (f *fakeMetrics) UpdateReferenceDec() { | |
| } | |
| func (f *fakeMetrics) DeleteReferenceInc() { | |
| } | |
| func (f *fakeMetrics) DeleteReferenceDec() { | |
| } | |
| func (f *fakeMetrics) AddUsageDimensions(className, queryType, op string, dims int) { | |
| f.Mock.MethodCalled("AddUsageDimensions", className, queryType, op, dims) | |
| } | |