Skip to content

Commit

Permalink
GODRIVER-2698 Decouple find constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
prestonvasquez committed Nov 15, 2023
1 parent 003f9b9 commit ea99f9b
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 22 deletions.
52 changes: 30 additions & 22 deletions mongo/collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -1642,29 +1642,18 @@ func (coll *Collection) Find(ctx context.Context, filter interface{},
return newCursorWithSession(bc, coll.bsonOpts, coll.registry, sess)
}

// FindOne executes a find command and returns a SingleResult for one document in the collection.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// returned. It cannot be nil. If the filter does not match any documents, a SingleResult with an error set to
// ErrNoDocuments will be returned. If the filter matches multiple documents, one will be selected from the matched set.
//
// The opts parameter can be used to specify options for this operation (see the options.FindOneOptions documentation).
//
// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/find/.
func (coll *Collection) FindOne(ctx context.Context, filter interface{},
opts ...*options.FindOneOptions) *SingleResult {

if ctx == nil {
ctx = context.Background()
func newFindOptionsFromFindOneOptions(opts ...*options.FindOneOptions) []*options.FindOptions {
if opts == nil {
return nil
}

findOpts := make([]*options.FindOptions, len(opts))
for idx, opt := range opts {
findOpts := []*options.FindOptions{}
for _, opt := range opts {
if opt == nil {
continue
}

findOpts[idx] = &options.FindOptions{
findOpts = append(findOpts, &options.FindOptions{
AllowPartialResults: opt.AllowPartialResults,
Collation: opt.Collation,
Comment: opt.Comment,
Expand All @@ -1677,14 +1666,33 @@ func (coll *Collection) FindOne(ctx context.Context, filter interface{},
ShowRecordID: opt.ShowRecordID,
Skip: opt.Skip,
Sort: opt.Sort,
}
})
}

// Unconditionally send a limit to make sure only one document is returned and the cursor is not kept open
// by the server.
findOpts[len(opts)] = options.Find().SetLimit(-1)
// Unconditionally send a limit to make sure only one document is returned and
// the cursor is not kept open by the server.
findOpts = append(findOpts, options.Find().SetLimit(-1))

return findOpts
}

// FindOne executes a find command and returns a SingleResult for one document in the collection.
//
// The filter parameter must be a document containing query operators and can be used to select the document to be
// returned. It cannot be nil. If the filter does not match any documents, a SingleResult with an error set to
// ErrNoDocuments will be returned. If the filter matches multiple documents, one will be selected from the matched set.
//
// The opts parameter can be used to specify options for this operation (see the options.FindOneOptions documentation).
//
// For more information about the command, see https://www.mongodb.com/docs/manual/reference/command/find/.
func (coll *Collection) FindOne(ctx context.Context, filter interface{},
opts ...*options.FindOneOptions) *SingleResult {

if ctx == nil {
ctx = context.Background()
}

cursor, err := coll.Find(ctx, filter, findOpts...)
cursor, err := coll.Find(ctx, filter, newFindOptionsFromFindOneOptions(opts...)...)
return &SingleResult{
ctx: ctx,
cur: cursor,
Expand Down
47 changes: 47 additions & 0 deletions mongo/collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,50 @@ func TestCollection(t *testing.T) {
assert.Equal(t, aggErr, err, "expected error %v, got %v", aggErr, err)
})
}

func TestNewFindOptionsFromFindOneOptions(t *testing.T) {
t.Parallel()

tests := []struct {
name string
opts []*options.FindOneOptions
want []*options.FindOptions
}{
{
name: "nil",
opts: nil,
want: nil,
},
{
name: "empty",
opts: []*options.FindOneOptions{},
want: []*options.FindOptions{
options.Find().SetLimit(-1),
},
},
{
name: "interior null",
opts: []*options.FindOneOptions{
options.FindOne().SetSkip(1),
nil,
options.FindOne().SetSkip(2),
},
want: []*options.FindOptions{
options.Find().SetSkip(1),
options.Find().SetSkip(2),
options.Find().SetLimit(-1),
},
},
}

for _, test := range tests {
test := test // Capture the range variable

t.Run(test.name, func(t *testing.T) {
t.Parallel()

got := newFindOptionsFromFindOneOptions(test.opts...)
assert.Equal(t, test.want, got)
})
}
}

0 comments on commit ea99f9b

Please sign in to comment.