Skip to content

Commit

Permalink
CLOUDP-67056: Implement search API in the go client (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
gssbzn committed Jul 15, 2020
1 parent d75c289 commit bdd98ee
Show file tree
Hide file tree
Showing 4 changed files with 589 additions and 1 deletion.
2 changes: 1 addition & 1 deletion githooks/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@ done
if [[ -n "${STAGED_GO_FILES}" ]]; then
set -o errexit
go test -race ./mongodbatlas...
make fix-lint
make lint-fix
set +o errexit
fi
2 changes: 2 additions & 0 deletions mongodbatlas/mongodbatlas.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ type Client struct {
Logs LogsService
DataLakes DataLakeService
OnlineArchives OnlineArchiveService
Search SearchService
CustomAWSDNS AWSCustomDNSService

onRequestCompleted RequestCompletionCallback
Expand Down Expand Up @@ -226,6 +227,7 @@ func NewClient(httpClient *http.Client) *Client {
c.Logs = &LogsServiceOp{Client: c}
c.DataLakes = &DataLakeServiceOp{Client: c}
c.OnlineArchives = &OnlineArchiveServiceOp{Client: c}
c.Search = &SearchServiceOp{Client: c}
c.CustomAWSDNS = &AWSCustomDNSServiceOp{Client: c}

return c
Expand Down
233 changes: 233 additions & 0 deletions mongodbatlas/search.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
package mongodbatlas

import (
"context"
"fmt"
"net/http"
)

const (
searchBasePath = "groups/%s/clusters/%s/fts"
)

// SearchService provides access to the search related functions in the Atlas API.
//
// See more: https://docs.atlas.mongodb.com/reference/api/atlas-search/
type SearchService interface {
ListIndexes(context.Context, string, string, string, string, *ListOptions) ([]*SearchIndex, *Response, error)
GetIndex(context.Context, string, string, string) (*SearchIndex, *Response, error)
CreateIndex(context.Context, string, string, *SearchIndex) (*SearchIndex, *Response, error)
UpdateIndex(context.Context, string, string, string, *SearchIndex) (*SearchIndex, *Response, error)
DeleteIndex(context.Context, string, string, string) (*Response, error)
ListAnalyzers(context.Context, string, string, *ListOptions) ([]*SearchAnalyzer, *Response, error)
}

// SearchServiceOp provides an implementation of the SearchService interface
type SearchServiceOp service

var _ SearchService = &SearchServiceOp{}

// ListIndexes Get all Atlas Search indexes for a specified collection.
//
// See more: https://docs.atlas.mongodb.com/reference/api/fts-indexes-get-all/
func (s *SearchServiceOp) ListIndexes(ctx context.Context, groupID, clusterName, databaseName, collectionName string, opts *ListOptions) ([]*SearchIndex, *Response, error) {
if groupID == "" {
return nil, nil, NewArgError("GroupID", "must be set")
}
if clusterName == "" {
return nil, nil, NewArgError("ClusterName", "must be set")
}
if databaseName == "" {
return nil, nil, NewArgError("databaseName", "must be set")
}
if collectionName == "" {
return nil, nil, NewArgError("collectionName", "must be set")
}

path := fmt.Sprintf(searchBasePath, groupID, clusterName)
path = fmt.Sprintf("%s/indexes/%s/%s", path, databaseName, collectionName)

path, err := setListOptions(path, opts)
if err != nil {
return nil, nil, err
}

req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}

var root []*SearchIndex
resp, err := s.Client.Do(ctx, req, &root)

return root, resp, err
}

// Get gets one Atlas Search index by its indexId.
//
// See more: https://docs.atlas.mongodb.com/reference/api/fts-indexes-get-one/
func (s *SearchServiceOp) GetIndex(ctx context.Context, groupID, clusterName, indexID string) (*SearchIndex, *Response, error) {
if groupID == "" {
return nil, nil, NewArgError("groupID", "must be set")
}
if clusterName == "" {
return nil, nil, NewArgError("clusterName", "must be set")
}
if indexID == "" {
return nil, nil, NewArgError("indexID", "must be set")
}

path := fmt.Sprintf(searchBasePath, groupID, clusterName)
path = fmt.Sprintf("%s/indexes/%s", path, indexID)

req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}

var root *SearchIndex
resp, err := s.Client.Do(ctx, req, &root)

return root, resp, err
}

// Create creates an Atlas Search index.
//
// See more: https://docs.atlas.mongodb.com/reference/api/fts-indexes-create-one/
func (s *SearchServiceOp) CreateIndex(ctx context.Context, projectID, clusterName string, r *SearchIndex) (*SearchIndex, *Response, error) {
if projectID == "" {
return nil, nil, NewArgError("projectID", "must be set")
}
if clusterName == "" {
return nil, nil, NewArgError("clusterName", "must be set")
}

path := fmt.Sprintf(searchBasePath, projectID, clusterName)
path = fmt.Sprintf("%s/indexes", path)

req, err := s.Client.NewRequest(ctx, http.MethodPost, path, r)
if err != nil {
return nil, nil, err
}

var root *SearchIndex
resp, err := s.Client.Do(ctx, req, &root)

return root, resp, err
}

// Update updates an Atlas Search index by its indexId.
//
// See more: https://docs.atlas.mongodb.com/reference/api/fts-indexes-update-one/
func (s *SearchServiceOp) UpdateIndex(ctx context.Context, projectID, clusterName, indexID string, r *SearchIndex) (*SearchIndex, *Response, error) {
if projectID == "" {
return nil, nil, NewArgError("projectID", "must be set")
}
if clusterName == "" {
return nil, nil, NewArgError("clusterName", "must be set")
}
if indexID == "" {
return nil, nil, NewArgError("indexID", "must be set")
}

path := fmt.Sprintf(searchBasePath, projectID, clusterName)
path = fmt.Sprintf("%s/indexes/%s", path, indexID)

req, err := s.Client.NewRequest(ctx, http.MethodPatch, path, r)
if err != nil {
return nil, nil, err
}

var root *SearchIndex
resp, err := s.Client.Do(ctx, req, &root)

return root, resp, err
}

// Delete deletes one Atlas Search index by its indexId.
//
// See more: https://docs.atlas.mongodb.com/reference/api/fts-indexes-delete-one/
func (s *SearchServiceOp) DeleteIndex(ctx context.Context, projectID, clusterName, indexID string) (*Response, error) {
if projectID == "" {
return nil, NewArgError("projectID", "must be set")
}
if clusterName == "" {
return nil, NewArgError("clusterName", "must be set")
}
if indexID == "" {
return nil, NewArgError("indexID", "must be set")
}

path := fmt.Sprintf(searchBasePath, projectID, clusterName)
path = fmt.Sprintf("%s/indexes/%s", path, indexID)

req, err := s.Client.NewRequest(ctx, http.MethodDelete, path, nil)
if err != nil {
return nil, err
}
resp, err := s.Client.Do(ctx, req, nil)

return resp, err
}

// ListAnalyzers gets all Atlas Search user-defined analyzers for a specified cluster.
//
// See more: https://docs.atlas.mongodb.com/reference/api/fts-analyzers-get-all/
func (s *SearchServiceOp) ListAnalyzers(ctx context.Context, groupID, clusterName string, listOptions *ListOptions) ([]*SearchAnalyzer, *Response, error) {
if groupID == "" {
return nil, nil, NewArgError("groupID", "must be set")
}
if clusterName == "" {
return nil, nil, NewArgError("clusterName", "must be set")
}

path := fmt.Sprintf(searchBasePath, groupID, clusterName)
path = fmt.Sprintf("%s/analyzers", path)

path, err := setListOptions(path, listOptions)
if err != nil {
return nil, nil, err
}

req, err := s.Client.NewRequest(ctx, http.MethodGet, path, nil)
if err != nil {
return nil, nil, err
}

var root []*SearchAnalyzer
resp, err := s.Client.Do(ctx, req, &root)

return root, resp, err
}

// SearchIndex index definition.
type SearchIndex struct {
Analyzer string `json:"analyzer,omitempty"`
CollectionName string `json:"collectionName"`
Database string `json:"database"`
IndexID string `json:"indexID,omitempty"`
Mappings *IndexMapping `json:"mappings,omitempty"`
Name string `json:"name"`
SearchAnalyzer string `json:"searchAnalyzer,omitempty"`
}

// IndexMapping containing index specifications for the collection fields.
type IndexMapping struct {
Dynamic bool `json:"dynamic"`
Fields *map[string]IndexField `json:"fields,omitempty"`
}

// IndexField field specifications.
type IndexField struct {
Analyzer string `json:"analyzer"`
Type string `json:"type"`
}

// SearchAnalyzer custom analyzer definition.
type SearchAnalyzer struct {
BaseAnalyzer string `json:"baseAnalyzer"`
MaxTokenLength *float64 `json:"maxTokenLength,omitempty"`
Name string `json:"name"`
StemExclusionSet []string `json:"stemExclusionSet,omitempty"`
Stopwords []string `json:"stopwords,omitempty"`
}
Loading

0 comments on commit bdd98ee

Please sign in to comment.