-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add WithMaxRows option to cap find() and countDocuments() results #17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Add functional options pattern to Execute() with WithMaxRows(n) that caps find() and countDocuments() results at the driver level. - Add ExecuteOption type and WithMaxRows() function - Apply min(queryLimit, maxRows) in executeFind and executeCountDocuments - Aggregate operations intentionally not affected - Add comprehensive tests for all limit scenarios Co-Authored-By: Claude Opus 4.5 <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request adds a WithMaxRows execute option to limit the maximum number of rows returned by find() and countDocuments() operations. The feature uses the functional options pattern for extensibility and applies min(queryLimit, maxRows) at the driver level.
Changes:
- Adds
WithMaxRows(n)functional option to cap results for find() and countDocuments() - Implements
computeEffectiveLimithelper to calculate min(queryLimit, maxRows) - Threads maxRows parameter through executor to affected operations (aggregate intentionally excluded)
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| client.go | Adds ExecuteOption pattern with WithMaxRows function and executeConfig |
| executor.go | Updates execute function to accept and pass maxRows parameter |
| internal/executor/executor.go | Threads maxRows parameter to executeFind and executeCountDocuments |
| internal/executor/collection.go | Implements computeEffectiveLimit helper and applies maxRows in find/count operations |
| collection_test.go | Adds comprehensive tests for maxRows behavior and backward compatibility |
| README.md | Documents WithMaxRows option with usage examples and behavior details |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // limit is min(N, maxRows). Aggregate operations are not affected. | ||
| func WithMaxRows(n int64) ExecuteOption { | ||
| return func(c *executeConfig) { |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The WithMaxRows function should validate that the input is positive. Negative or zero values don't make semantic sense for limiting maximum rows and could lead to unexpected behavior. Consider adding validation to reject n <= 0 or documenting that negative/zero values are allowed and their semantics.
| // limit is min(N, maxRows). Aggregate operations are not affected. | |
| func WithMaxRows(n int64) ExecuteOption { | |
| return func(c *executeConfig) { | |
| // limit is min(N, maxRows). Aggregate operations are not affected. If n <= 0, | |
| // this option is ignored. | |
| func WithMaxRows(n int64) ExecuteOption { | |
| return func(c *executeConfig) { | |
| if n <= 0 { | |
| // Ignore non-positive values to avoid nonsensical limits. | |
| return | |
| } |
| func TestWithMaxRowsCapsResults(t *testing.T) { | ||
| client := testutil.GetClient(t) | ||
| dbName := "testdb_maxrows_cap" | ||
| defer testutil.CleanupDatabase(t, client, dbName) | ||
|
|
||
| ctx := context.Background() | ||
|
|
||
| // Insert 20 documents | ||
| collection := client.Database(dbName).Collection("items") | ||
| docs := make([]any, 20) | ||
| for i := 0; i < 20; i++ { | ||
| docs[i] = bson.M{"index": i} | ||
| } | ||
| _, err := collection.InsertMany(ctx, docs) | ||
| require.NoError(t, err) | ||
|
|
||
| gc := gomongo.NewClient(client) | ||
|
|
||
| // Without MaxRows - returns all 20 | ||
| result, err := gc.Execute(ctx, dbName, "db.items.find()") | ||
| require.NoError(t, err) | ||
| require.Equal(t, 20, result.RowCount) | ||
|
|
||
| // With MaxRows(10) - caps at 10 | ||
| result, err = gc.Execute(ctx, dbName, "db.items.find()", gomongo.WithMaxRows(10)) | ||
| require.NoError(t, err) | ||
| require.Equal(t, 10, result.RowCount) | ||
| } | ||
|
|
||
| func TestWithMaxRowsQueryLimitTakesPrecedence(t *testing.T) { | ||
| client := testutil.GetClient(t) | ||
| dbName := "testdb_maxrows_query_limit" | ||
| defer testutil.CleanupDatabase(t, client, dbName) | ||
|
|
||
| ctx := context.Background() | ||
|
|
||
| // Insert 20 documents | ||
| collection := client.Database(dbName).Collection("items") | ||
| docs := make([]any, 20) | ||
| for i := 0; i < 20; i++ { | ||
| docs[i] = bson.M{"index": i} | ||
| } | ||
| _, err := collection.InsertMany(ctx, docs) | ||
| require.NoError(t, err) | ||
|
|
||
| gc := gomongo.NewClient(client) | ||
|
|
||
| // Query limit(5) is smaller than MaxRows(100) - should return 5 | ||
| result, err := gc.Execute(ctx, dbName, "db.items.find().limit(5)", gomongo.WithMaxRows(100)) | ||
| require.NoError(t, err) | ||
| require.Equal(t, 5, result.RowCount) | ||
| } | ||
|
|
||
| func TestWithMaxRowsTakesPrecedenceOverLargerLimit(t *testing.T) { | ||
| client := testutil.GetClient(t) | ||
| dbName := "testdb_maxrows_precedence" | ||
| defer testutil.CleanupDatabase(t, client, dbName) | ||
|
|
||
| ctx := context.Background() | ||
|
|
||
| // Insert 20 documents | ||
| collection := client.Database(dbName).Collection("items") | ||
| docs := make([]any, 20) | ||
| for i := 0; i < 20; i++ { | ||
| docs[i] = bson.M{"index": i} | ||
| } | ||
| _, err := collection.InsertMany(ctx, docs) | ||
| require.NoError(t, err) | ||
|
|
||
| gc := gomongo.NewClient(client) | ||
|
|
||
| // Query limit(100) is larger than MaxRows(5) - should return 5 | ||
| result, err := gc.Execute(ctx, dbName, "db.items.find().limit(100)", gomongo.WithMaxRows(5)) | ||
| require.NoError(t, err) | ||
| require.Equal(t, 5, result.RowCount) | ||
| } | ||
|
|
||
| func TestExecuteBackwardCompatibility(t *testing.T) { | ||
| client := testutil.GetClient(t) | ||
| dbName := "testdb_backward_compat" | ||
| defer testutil.CleanupDatabase(t, client, dbName) | ||
|
|
||
| ctx := context.Background() | ||
|
|
||
| collection := client.Database(dbName).Collection("items") | ||
| _, err := collection.InsertMany(ctx, []any{ | ||
| bson.M{"name": "a"}, | ||
| bson.M{"name": "b"}, | ||
| bson.M{"name": "c"}, | ||
| }) | ||
| require.NoError(t, err) | ||
|
|
||
| gc := gomongo.NewClient(client) | ||
|
|
||
| // Execute without options should work (backward compatible) | ||
| result, err := gc.Execute(ctx, dbName, "db.items.find()") | ||
| require.NoError(t, err) | ||
| require.Equal(t, 3, result.RowCount) | ||
| } | ||
|
|
||
| func TestCountDocumentsWithMaxRows(t *testing.T) { | ||
| client := testutil.GetClient(t) | ||
| dbName := "testdb_count_maxrows" | ||
| defer testutil.CleanupDatabase(t, client, dbName) | ||
|
|
||
| ctx := context.Background() | ||
|
|
||
| // Insert 100 documents | ||
| collection := client.Database(dbName).Collection("items") | ||
| docs := make([]any, 100) | ||
| for i := 0; i < 100; i++ { | ||
| docs[i] = bson.M{"index": i} | ||
| } | ||
| _, err := collection.InsertMany(ctx, docs) | ||
| require.NoError(t, err) | ||
|
|
||
| gc := gomongo.NewClient(client) | ||
|
|
||
| // Without MaxRows - counts all 100 | ||
| result, err := gc.Execute(ctx, dbName, "db.items.countDocuments()") | ||
| require.NoError(t, err) | ||
| require.Equal(t, "100", result.Rows[0]) | ||
|
|
||
| // With MaxRows(50) - counts up to 50 | ||
| result, err = gc.Execute(ctx, dbName, "db.items.countDocuments()", gomongo.WithMaxRows(50)) | ||
| require.NoError(t, err) | ||
| require.Equal(t, "50", result.Rows[0]) | ||
| } |
Copilot
AI
Jan 22, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding test coverage for edge cases such as WithMaxRows(0), WithMaxRows with negative values, and combining maxRows with skip operations. These edge cases could expose unexpected behavior and help validate the API's robustness.
Summary
WithMaxRows(n)execute option to limit maximum rows returnedmin(queryLimit, maxRows)at driver level forfind()andcountDocuments()$limitstage instead)Usage
Test plan
🤖 Generated with Claude Code