Skip to content

Commit

Permalink
GODRIVER-2859 Add search index management helpers.
Browse files Browse the repository at this point in the history
  • Loading branch information
qingyang-hu committed Jul 13, 2023
1 parent a09e00c commit a154b3a
Show file tree
Hide file tree
Showing 11 changed files with 1,191 additions and 7 deletions.
16 changes: 11 additions & 5 deletions bson/raw.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,18 @@ func (r Raw) LookupErr(key ...string) (RawValue, error) {
// elements. If the document is not valid, the elements up to the invalid point will be returned
// along with an error.
func (r Raw) Elements() ([]RawElement, error) {
elems, err := bsoncore.Document(r).Elements()
relems := make([]RawElement, 0, len(elems))
for _, elem := range elems {
relems = append(relems, RawElement(elem))
var relems []RawElement
if doc := bsoncore.Document(r); len(doc) > 0 {
elems, err := doc.Elements()
if err != nil {
return relems, err
}
relems = make([]RawElement, 0, len(elems))
for _, elem := range elems {
relems = append(relems, RawElement(elem))
}
}
return relems, err
return relems, nil
}

// Values returns this document as a slice of values. The returned slice will contain valid values.
Expand Down
7 changes: 7 additions & 0 deletions mongo/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -1767,6 +1767,13 @@ func (coll *Collection) Indexes() IndexView {
return IndexView{coll: coll}
}

// SearchIndexes returns a SearchIndexView instance that can be used to perform operations on the search indexes for the collection.
func (coll *Collection) SearchIndexes() SearchIndexView {
return SearchIndexView{
coll: coll,
}
}

// Drop drops the collection on the server. This method ignores "namespace not found" errors so it is safe to drop
// a collection that does not exist on the server.
func (coll *Collection) Drop(ctx context.Context) error {
Expand Down
173 changes: 173 additions & 0 deletions mongo/integration/unified/collection_operation_execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,80 @@ func executeCreateIndex(ctx context.Context, operation *operation) (*operationRe
return newValueResult(bsontype.String, bsoncore.AppendString(nil, name), err), nil
}

func executeCreateSearchIndex(ctx context.Context, operation *operation) (*operationResult, error) {
coll, err := entities(ctx).collection(operation.Object)
if err != nil {
return nil, err
}

var model mongo.SearchIndexModel

elems, err := operation.Arguments.Elements()
if err != nil {
return nil, err
}
for _, elem := range elems {
key := elem.Key()
val := elem.Value()

switch key {
case "model":
err = bson.Unmarshal(val.Document(), &model)
if err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("unrecognized createSearchIndex option %q", key)
}
}

name, err := coll.SearchIndexes().CreateOne(ctx, model)
return newValueResult(bsontype.String, bsoncore.AppendString(nil, name), err), nil
}

func executeCreateSearchIndexes(ctx context.Context, operation *operation) (*operationResult, error) {
coll, err := entities(ctx).collection(operation.Object)
if err != nil {
return nil, err
}

var models []mongo.SearchIndexModel

elems, err := operation.Arguments.Elements()
if err != nil {
return nil, err
}
for _, elem := range elems {
key := elem.Key()
val := elem.Value()

switch key {
case "models":
vals, err := val.Array().Values()
if err != nil {
return nil, err
}
for _, val := range vals {
var model mongo.SearchIndexModel
err = bson.Unmarshal(val.Value, &model)
if err != nil {
return nil, err
}
models = append(models, model)
}
default:
return nil, fmt.Errorf("unrecognized createSearchIndexes option %q", key)
}
}

names, err := coll.SearchIndexes().CreateMany(ctx, models)
builder := bsoncore.NewArrayBuilder()
for _, name := range names {
builder.AppendString(name)
}
return newValueResult(bsontype.Array, builder.Build(), err), nil
}

func executeDeleteOne(ctx context.Context, operation *operation) (*operationResult, error) {
coll, err := entities(ctx).collection(operation.Object)
if err != nil {
Expand Down Expand Up @@ -522,6 +596,34 @@ func executeDropIndexes(ctx context.Context, operation *operation) (*operationRe
return newDocumentResult(res, err), nil
}

func executeDropSearchIndex(ctx context.Context, operation *operation) (*operationResult, error) {
coll, err := entities(ctx).collection(operation.Object)
if err != nil {
return nil, err
}

var name string

elems, err := operation.Arguments.Elements()
if err != nil {
return nil, err
}
for _, elem := range elems {
key := elem.Key()
val := elem.Value()

switch key {
case "name":
name = val.StringValue()
default:
return nil, fmt.Errorf("unrecognized dropSearchIndex option %q", key)
}
}

err = coll.SearchIndexes().DropOne(ctx, name)
return newValueResult(bsontype.Null, nil, err), nil
}

func executeEstimatedDocumentCount(ctx context.Context, operation *operation) (*operationResult, error) {
coll, err := entities(ctx).collection(operation.Object)
if err != nil {
Expand Down Expand Up @@ -1009,6 +1111,43 @@ func executeListIndexes(ctx context.Context, operation *operation) (*operationRe
return newCursorResult(docs), nil
}

func executeListSearchIndexes(ctx context.Context, operation *operation) (*operationResult, error) {
coll, err := entities(ctx).collection(operation.Object)
if err != nil {
return nil, err
}

var name *string
var opts []*options.AggregateOptions

elems, err := operation.Arguments.Elements()
if err != nil {
return nil, err
}
for _, elem := range elems {
key := elem.Key()
val := elem.Value()

switch key {
case "name":
n := val.StringValue()
name = &n
case "aggregationOptions":
var opt options.AggregateOptions
err = bson.Unmarshal(val.Document(), &opt)
if err != nil {
return nil, err
}
opts = append(opts, &opt)
default:
return nil, fmt.Errorf("unrecognized listSearchIndexes option %q", key)
}
}

_, err = coll.SearchIndexes().List(ctx, name, opts)
return newValueResult(bsontype.Null, nil, err), nil
}

func executeRenameCollection(ctx context.Context, operation *operation) (*operationResult, error) {
coll, err := entities(ctx).collection(operation.Object)
if err != nil {
Expand Down Expand Up @@ -1145,6 +1284,40 @@ func executeUpdateMany(ctx context.Context, operation *operation) (*operationRes
return newDocumentResult(raw, err), nil
}

func executeUpdateSearchIndex(ctx context.Context, operation *operation) (*operationResult, error) {
coll, err := entities(ctx).collection(operation.Object)
if err != nil {
return nil, err
}

var name string
var definition interface{}

elems, err := operation.Arguments.Elements()
if err != nil {
return nil, err
}
for _, elem := range elems {
key := elem.Key()
val := elem.Value()

switch key {
case "name":
name = val.StringValue()
case "definition":
err = bson.Unmarshal(val.Value, &definition)
if err != nil {
return nil, err
}
default:
return nil, fmt.Errorf("unrecognized updateSearchIndex option %q", key)
}
}

err = coll.SearchIndexes().UpdateOne(ctx, name, definition)
return newValueResult(bsontype.Null, nil, err), nil
}

func buildUpdateResultDocument(res *mongo.UpdateResult) (bsoncore.Document, error) {
if res == nil {
return emptyCoreDocument, nil
Expand Down
14 changes: 12 additions & 2 deletions mongo/integration/unified/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,10 +146,14 @@ func (op *operation) run(ctx context.Context, loopDone <-chan struct{}) (*operat
return executeBulkWrite(ctx, op)
case "countDocuments":
return executeCountDocuments(ctx, op)
case "createIndex":
return executeCreateIndex(ctx, op)
case "createFindCursor":
return executeCreateFindCursor(ctx, op)
case "createIndex":
return executeCreateIndex(ctx, op)
case "createSearchIndex":
return executeCreateSearchIndex(ctx, op)
case "createSearchIndexes":
return executeCreateSearchIndexes(ctx, op)
case "deleteOne":
return executeDeleteOne(ctx, op)
case "deleteMany":
Expand All @@ -160,6 +164,8 @@ func (op *operation) run(ctx context.Context, loopDone <-chan struct{}) (*operat
return executeDropIndex(ctx, op)
case "dropIndexes":
return executeDropIndexes(ctx, op)
case "dropSearchIndex":
return executeDropSearchIndex(ctx, op)
case "estimatedDocumentCount":
return executeEstimatedDocumentCount(ctx, op)
case "find":
Expand All @@ -178,6 +184,8 @@ func (op *operation) run(ctx context.Context, loopDone <-chan struct{}) (*operat
return executeInsertOne(ctx, op)
case "listIndexes":
return executeListIndexes(ctx, op)
case "listSearchIndexes":
return executeListSearchIndexes(ctx, op)
case "rename":
// "rename" can either target a collection or a GridFS bucket.
if _, err := entities(ctx).collection(op.Object); err == nil {
Expand All @@ -193,6 +201,8 @@ func (op *operation) run(ctx context.Context, loopDone <-chan struct{}) (*operat
return executeUpdateOne(ctx, op)
case "updateMany":
return executeUpdateMany(ctx, op)
case "updateSearchIndex":
return executeUpdateSearchIndex(ctx, op)

// GridFS operations
case "delete":
Expand Down
1 change: 1 addition & 0 deletions mongo/integration/unified/unified_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ var (
"client-side-encryption/unified",
"client-side-operations-timeout",
"gridfs",
"index-management",
}
failDirectories = []string{
"unified-test-format/valid-fail",
Expand Down
24 changes: 24 additions & 0 deletions mongo/options/searchindexoptions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (C) MongoDB, Inc. 2023-present.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

package options

// CreateSearchIndexesOptions represents options that can be used to configure a SearchIndexView.CreateOne or
// SearchIndexView.CreateMany operation.
type CreateSearchIndexesOptions struct {
}

// ListSearchIndexesOptions represents options that can be used to configure a SearchIndexView.List operation.
type ListSearchIndexesOptions struct {
}

// DropSearchIndexOptions represents options that can be used to configure a SearchIndexView.DropOne operation.
type DropSearchIndexOptions struct {
}

// UpdateSearchIndexOptions represents options that can be used to configure a SearchIndexView.UpdateOne operation.
type UpdateSearchIndexOptions struct {
}
Loading

0 comments on commit a154b3a

Please sign in to comment.