github.com/weaviate/weaviate@v1.24.6/adapters/handlers/graphql/local/explore/concepts_resolver.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package explore 13 14 import ( 15 "context" 16 "fmt" 17 18 "github.com/tailor-inc/graphql" 19 "github.com/tailor-inc/graphql/language/ast" 20 "github.com/weaviate/weaviate/adapters/handlers/graphql/local/common_filters" 21 enterrors "github.com/weaviate/weaviate/entities/errors" 22 "github.com/weaviate/weaviate/entities/models" 23 "github.com/weaviate/weaviate/entities/search" 24 "github.com/weaviate/weaviate/usecases/traverser" 25 ) 26 27 // Resolver is a local interface that can be composed with other interfaces to 28 // form the overall GraphQL API main interface. All data-base connectors that 29 // want to support the Meta feature must implement this interface. 30 type Resolver interface { 31 Explore(ctx context.Context, principal *models.Principal, 32 params traverser.ExploreParams) ([]search.Result, error) 33 } 34 35 // RequestsLog is a local abstraction on the RequestsLog that needs to be 36 // provided to the graphQL API in order to log Local.Fetch queries. 37 type RequestsLog interface { 38 Register(requestType string, identifier string) 39 } 40 41 type resources struct { 42 resolver Resolver 43 } 44 45 func newResources(s interface{}) (*resources, error) { 46 source, ok := s.(map[string]interface{}) 47 if !ok { 48 return nil, fmt.Errorf("expected source to be a map, but was %T", source) 49 } 50 51 resolver, ok := source["Resolver"].(Resolver) 52 if !ok { 53 return nil, fmt.Errorf("expected source to contain a usable Resolver, but was %#v", source) 54 } 55 56 return &resources{ 57 resolver: resolver, 58 }, nil 59 } 60 61 type resolver struct { 62 modulesProvider ModulesProvider 63 } 64 65 func newResolver(modulesProvider ModulesProvider) *resolver { 66 return &resolver{modulesProvider} 67 } 68 69 func (r *resolver) resolve(p graphql.ResolveParams) (interface{}, error) { 70 result, err := r.resolveExplore(p) 71 if err != nil { 72 return result, enterrors.NewErrGraphQLUser(err, "Explore", "") 73 } 74 return result, nil 75 } 76 77 func (r *resolver) resolveExplore(p graphql.ResolveParams) (interface{}, error) { 78 resources, err := newResources(p.Source) 79 if err != nil { 80 return nil, err 81 } 82 83 params := traverser.ExploreParams{} 84 85 if param, ok := p.Args["nearVector"]; ok { 86 extracted, err := common_filters.ExtractNearVector(param.(map[string]interface{})) 87 if err != nil { 88 return nil, fmt.Errorf("failed to extract nearVector params: %s", err) 89 } 90 params.NearVector = &extracted 91 } 92 93 if param, ok := p.Args["nearObject"]; ok { 94 extracted, err := common_filters.ExtractNearObject(param.(map[string]interface{})) 95 if err != nil { 96 return nil, fmt.Errorf("failed to extract nearObject params: %s", err) 97 } 98 params.NearObject = &extracted 99 } 100 101 if param, ok := p.Args["offset"]; ok { 102 params.Offset = param.(int) 103 } 104 105 if param, ok := p.Args["limit"]; ok { 106 params.Limit = param.(int) 107 } 108 109 if r.modulesProvider != nil { 110 extractedParams := r.modulesProvider.CrossClassExtractSearchParams(p.Args) 111 if len(extractedParams) > 0 { 112 params.ModuleParams = extractedParams 113 } 114 } 115 116 if containsCertaintyProperty(p.Info) { 117 params.WithCertaintyProp = true 118 } 119 120 return resources.resolver.Explore(p.Context, 121 principalFromContext(p.Context), params) 122 } 123 124 func principalFromContext(ctx context.Context) *models.Principal { 125 principal := ctx.Value("principal") 126 if principal == nil { 127 return nil 128 } 129 130 return principal.(*models.Principal) 131 } 132 133 func containsCertaintyProperty(info graphql.ResolveInfo) bool { 134 if len(info.FieldASTs) == 0 { 135 return false 136 } 137 138 for _, selection := range info.FieldASTs[0].SelectionSet.Selections { 139 field := selection.(*ast.Field) 140 name := field.Name.Value 141 if name == "certainty" { 142 return true 143 } 144 } 145 146 return false 147 }