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  }