Skip to content

Driver v2: options struct literals become builders; drop MaxTime; ArrayFilters and Delete option changes #3

Description

@TopherGopher

Part of the easymongo refactor (see PLAN.md on the refactor branch).

Working context (read this first)

Why

Driver v2 collection methods take options.Lister[T] values. The &options.FindOptions{...} struct literals easymongo passes today no longer satisfy that interface. MaxTime fields were removed in favour of context deadlines, which easymongo already applies through Query.getContext() in query.go.

Scope

Convert each literal to a builder chain that only sets fields whose easymongo value is non-nil:

  • find_query.go: FindOneOptions (99-114), FindOptions (140-166), CountOptions (182-191), DistinctOptions (206-209).
  • aggregate.go: AggregateOptions (40-51).
  • update_query.go: UpdateOptions (52-61). ArrayFilters changes from options.ArrayFilters to []any; update UpdateQuery.arrayFilters and its setter.
  • delete_query.go: DeleteOptions (25-31) splits into DeleteOneOptions and DeleteManyOptions builders (options.DeleteOne(), options.DeleteMany()).
  • find_and_query.go: FindOneAndUpdateOptions (127-141), FindOneAndReplaceOptions (147-160), FindOneAndDeleteOptions (191-201); ArrayFilters as above; options.ReturnDocument, options.Before, options.After are unchanged.
  • Delete every MaxTime: assignment; confirm getContext() is applied to each of these calls so the timeout still takes effect.
  • insert_query.go, replace_query.go, index.go, database.go already use constructors (options.InsertOne(), options.Replace(), options.CreateIndexes(), options.ListCollections().SetNameOnly(true), options.Collection()); verify they compile and that Index types still match.
  • Keep the fluent easymongo API unchanged; this is an internal change.

Implementation details

options.Lister[T] is interface{ List() []func(*T) error }; every options.Find()-style builder satisfies it. Builder setters verified in v2.9.0 for FindOptionsBuilder: SetAllowDiskUse, SetAllowPartialResults, SetBatchSize(int32), SetCollation(*options.Collation), SetComment(any), SetHint(any), SetLimit(int64), SetProjection(any), SetSkip(int64), SetSort(any), SetNoCursorTimeout(bool). FindOne(), Count(), Distinct(), Aggregate(), UpdateOne(), UpdateMany(), DeleteOne(), DeleteMany(), FindOneAndUpdate(), FindOneAndReplace(), FindOneAndDelete() have the matching subsets. UpdateOptions.ArrayFilters is []any with SetArrayFilters([]any). Collection method shapes, for example: coll.Find(ctx, filter any, opts ...options.Lister[options.FindOptions]) (*mongo.Cursor, error), coll.DeleteOne(ctx, filter any, opts ...options.Lister[options.DeleteOneOptions]) (*mongo.DeleteResult, error).

Conversion pattern to apply everywhere (only set what the easymongo query has):

// before (v1)
opts := &options.FindOptions{Limit: q.limit, Skip: q.skip, Sort: q.sortFields, MaxTime: q.timeout}
// after (v2)
opts := options.Find()
if q.limit != nil { opts.SetLimit(*q.limit) }
if q.skip != nil  { opts.SetSkip(*q.skip) }
if len(q.sortFields) > 0 { opts.SetSort(q.sortFields) }
// MaxTime dropped: the ctx from q.getContext() already carries the deadline

Where easymongo stored *options.ArrayFilters, store []any and change the setter's parameter type to []any (or keep a ...any variadic for convenience).

For DeleteQuery, build options.DeleteOne() in One() and options.DeleteMany() in Many() from the same Collation/Hint fields.

Tests first

Existing tests for each file must pass unchanged. Add:

  • A unit test per builder helper that a fully populated easymongo query yields the expected driver options (inspect the built options by applying the Lister to a zero struct).
  • Timeout on a FindQuery still cancels a deliberately slow query ($where sleep or a large Limit on a big collection) with ErrTimeoutOccurred.
  • Array filters: an update with ArrayFilters on a nested array succeeds (update_query_test.go).

Acceptance

  • go vet ./... clean; no reference to MaxTime or options.ArrayFilters remains.

Depends on: #2. Lands in the same pull request as #2, #4 and #5.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions