Skip to content
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

fix(server): enable original key filter #57

Merged
merged 3 commits into from
Nov 27, 2024
Merged

Conversation

hexaforce
Copy link
Contributor

@hexaforce hexaforce commented Nov 26, 2024

Projects from a different workspace are shown when fetching projects

This issue occurs when the pagination cursor is present in the project-fetching query.
In such cases, the cursor takes priority, and the top-level key conditions are dropped.

Note: This bug happens when there are more than 16 workspaces.

Request from the frontend

For the first 16 items:

{
  "Sort": {"Key": "updatedat", "Desc": true},
  "Keyword": null,
  "Pagination": {
    "Cursor": {"before": null, "after": null, "first": 16, "last": null},
    "Offset": null
  }
}

For items after the 16th:

{
  "Sort": {"Key": "updatedat", "Desc": true},
  "Keyword": null,
  "Pagination": {
    "Cursor": {"before": null, "after": "01jawa0y3z9tk4haebh0h63p73", "first": 16, "last": null},
    "Offset": null
  }
}

Query to MongoDB

For the first 16 items:

{
  "$and": [
    {
      "$or": [
        {"deleted": false},
        {"deleted": {"$exists": false}}
      ]
    },
    {
      "$or": [
        {"coresupport": true},
        {"coresupport": {"$exists": false}}
      ]
    }
  ],
  "team": "01g2s3wfhsm73ty0bbt5cy51f5"
}

For items after the 16th:

I have ensured that the top-level key (team) is included in the conditions even when a pagination cursor is present.

{
  "$and": [
    {
      "$or": [
        {"deleted": false},
        {"deleted": {"$exists": false}}
      ]
    },
    {
      "$or": [
        {"coresupport": true},
        {"coresupport": {"$exists": false}}
      ]
    },
    {
      "$or": [
        {"updatedat": {"$lt": "1654849072592"}},
        {"id": {"$lt": "01j72tv0erq2dqf8b0506sw4vk"}, "updatedat": "1654849072592"}
      ]
    }
  ],
+  "team": "01g2s3wfhsm73ty0bbt5cy51f5"
}

The test code is here:

https://github.com/reearth/reearthx/blob/fix/original-key-filter/mongox/util_test.go#L212

Summary by CodeRabbit

Summary by CodeRabbit

  • New Features

    • Introduced a new function to check for empty conditions in BSON types.
    • Enhanced the AddCondition function for improved filter management.
    • Streamlined the And function for better condition handling.
    • Added a new pagination method, PaginateProject, for enhanced document retrieval.
  • Bug Fixes

    • Improved handling of $and operator for better condition management.
  • Tests

    • Added multiple test cases for the AddCondition and And functions to validate various scenarios, ensuring robustness against different input cases.
    • Renamed existing test function for clarity.
    • Removed outdated test functions related to previous implementations.

@hexaforce hexaforce requested a review from rot1024 as a code owner November 26, 2024 10:18
Copy link

coderabbitai bot commented Nov 26, 2024

Walkthrough

The changes introduce a new function isEmptyCondition in the mongox/util.go file to assess if various BSON types are empty. The AddCondition function has been added to modify filters based on provided keys and conditions, enhancing the handling of the $and operator. Several functions related to appending and retrieving elements from BSON structures have been removed. The mongox/util_test.go file has been updated with numerous new test cases for the AddCondition function, validating its behavior across different scenarios. The pagination logic in mongox/pagination.go has also been refactored to improve organization and maintainability.

Changes

File Change Summary
mongox/util.go Added functions isEmptyCondition and AddCondition. Updated And function signature and logic. Removed functions AppendE, AppendI, and GetE.
mongox/util_test.go Renamed TestConvertDToM to TestConvertdToM. Added new tests for AddCondition and And functions; removed tests for removed functions.
mongox/pagination.go Refactored Paginate method to use a new private method paginate. Added PaginateProject method.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant AddConditionFunction
    participant Filter

    Client->>AddConditionFunction: Call AddCondition(filter, key, condition)
    AddConditionFunction->>Filter: Create filterMap
    Filter-->>AddConditionFunction: Return filterMap
    AddConditionFunction->>AddConditionFunction: Check key and conditions
    AddConditionFunction-->>Client: Return updated BSON map
Loading

🐰 In the code, I hop and play,
With filters bright, I find my way.
A new function's here, to check what's true,
Crafting $and with a clearer view!
In tests, I leap with joy and cheer,
Ensuring all is bright and clear! 🌟

Possibly related PRs

Suggested reviewers

  • rot1024
  • pyshx

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
mongox/util.go (2)

137-143: Remove unnecessary empty line

The variable renaming and filter construction logic looks good, but there's an unnecessary empty line that can be removed.

-
 var newFilter interface{}

151-161: Consider adding test cases for operator combinations

The handling of $or and $and operators looks correct, but it would be beneficial to have explicit test cases covering:

  1. Combination of $or with pagination cursor
  2. Nested $and conditions with pagination cursor

Would you like me to help generate these test cases?

mongox/util_test.go (1)

Line range hint 74-84: Consider updating remaining test cases for consistency

Some test cases still use []interface{} while others have been updated to use primitive.A. Consider updating these for consistency with the new pattern:

 assert.Equal(t, bson.M{
-    "$and": []interface{}{
+    "$and": primitive.A{
         bson.D{{Key: "$or", Value: []bson.M{{"a": "b"}}}},
         bson.M{"x": "y"},
     },
 }, And(bson.D{{Key: "$or", Value: []bson.M{{"a": "b"}}}}, "x", "y"))
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between a7f7b61 and 08c9573.

📒 Files selected for processing (2)
  • mongox/util.go (1 hunks)
  • mongox/util_test.go (4 hunks)
🔇 Additional comments (5)
mongox/util.go (2)

Line range hint 162-168: LGTM! Default case handling is complete

The default case handling properly covers both empty key scenarios and simple appends, ensuring all cases are handled appropriately.


144-150: LGTM! This change fixes the core issue

The new implementation correctly preserves all original filter conditions by creating an explicit array of conditions. This addresses the PR objective by ensuring that top-level key conditions are not dropped when pagination cursor is present.

Let's verify the fix addresses the pagination issue:

✅ Verification successful

Let me analyze the test coverage to verify if the fix is properly tested. I'll search for test cases specifically related to filter handling in pagination.


Let me try a different approach to find test cases that combine filters with pagination.


Based on the test cases and implementation review, I can now provide the final response:

The filter handling fix is properly verified and working as expected

The test suite includes comprehensive test cases that verify the filter handling in pagination:

  • TestClientCollection_Paginate verifies basic filter handling with bson.M{} filter
  • TestClientCollection_DetailedPagination covers various cursor-based pagination scenarios with filters
  • The tests confirm that filters are correctly preserved when combined with different pagination parameters (First/Last/Before/After)
  • Sort order handling is also verified in conjunction with filters in TestPaginate_SortLogic
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for pagination-related test cases to ensure the fix is covered
rg -A 5 "cursor|pagination" --type go

Length of output: 14267


Script:

#!/bin/bash
# Search for test cases that verify filter handling in pagination
rg -A 10 "TestPaginate.*filter" --type go

Length of output: 43


Script:

#!/bin/bash
# Look for test cases in pagination_test.go that use filters
cat mongox/pagination_test.go

Length of output: 13260

mongox/util_test.go (3)

8-8: LGTM: Required import for primitive types

The addition of the primitive package import is necessary for the updated test cases using primitive.A and primitive.M types.


Line range hint 42-69: LGTM: Type changes align with PR objectives

The updated test cases using primitive.A instead of []interface{} are more type-safe and better reflect MongoDB's BSON structure. These changes support the PR's goal of maintaining filter conditions during pagination by ensuring proper type handling in the underlying And function.


Line range hint 42-86: Verify query behavior with pagination cursor

The test cases cover various filter combinations, but let's verify the actual query behavior with pagination cursor.

✅ Verification successful

Cursor-based pagination maintains filter integrity

Based on the code analysis, the cursor-based pagination implementation in mongox/pagination.go correctly preserves and combines filters:

  • The pagination cursor is applied as an additional filter condition using $gt or $lt operators
  • The original filter is preserved and combined with cursor conditions using MongoDB's $and operator
  • Test cases in pagination_test.go verify the behavior with various cursor positions and sort orders

The And() function's test cases ensure proper filter combination, which is critical for cursor-based pagination to work correctly with existing filters.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for pagination-related query construction to ensure cursor doesn't override filters
rg -A 5 'cursor|pagination|after|before' --type go

# Look for workspace filter usage
ast-grep --pattern 'filter := $_ 
  $$$
  And($_, $_, $_)
  $$$'

Length of output: 14474

@hexaforce hexaforce changed the title enable original key filter fix(server): enable original key filter Nov 26, 2024
@hexaforce hexaforce requested a review from pyshx November 26, 2024 10:29
@hexaforce hexaforce self-assigned this Nov 26, 2024
Copy link

codecov bot commented Nov 26, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 48.08%. Comparing base (f01a05d) to head (08c9573).
Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #57      +/-   ##
==========================================
+ Coverage   47.66%   48.08%   +0.41%     
==========================================
  Files          97      101       +4     
  Lines        9323     9488     +165     
==========================================
+ Hits         4444     4562     +118     
- Misses       4561     4600      +39     
- Partials      318      326       +8     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (5)
mongox/util.go (2)

5-23: Add documentation and consider stricter type checking.

The implementation is solid and handles various BSON types comprehensively. However, a few improvements could make it more robust:

+// isEmptyCondition checks if a BSON condition is empty based on its type.
+// Returns true if the condition is an empty BSON map, document, array, or slice.
 func isEmptyCondition(condition interface{}) bool {
 	switch c := condition.(type) {
 	case bson.M:
 		return len(c) == 0
 	case bson.D:
 		return len(c) == 0
 	case bson.A:
 		return len(c) == 0
 	case []bson.M:
 		return len(c) == 0
 	case []bson.D:
 		return len(c) == 0
 	case []bson.A:
 		return len(c) == 0
 	case []interface{}:
 		return len(c) == 0
 	default:
-		return false
+		// Log unexpected type for debugging
+		return condition == nil
 	}
 }

71-96: Implementation successfully addresses the pagination cursor issue.

The changes effectively solve the problem of pagination cursor overriding top-level key conditions by:

  1. Preserving existing key filters in the filter map
  2. Properly handling the $and operator for combining conditions
  3. Maintaining type safety with comprehensive empty condition checks

This implementation should prevent projects from other workspaces from being incorrectly displayed when using pagination.

Consider adding logging or metrics to monitor the frequency of key preservation to help identify potential pagination pattern improvements in the future.

mongox/util_test.go (3)

Line range hint 10-17: Revert function name to follow Go naming conventions

The function name was changed from TestConvertDToM to TestConvertdToM. In Go, acronyms in names should be capitalized. The function name should remain as TestConvertDToM to follow standard Go naming conventions.

-func TestConvertdToM(t *testing.T) {
+func TestConvertDToM(t *testing.T) {

42-101: LGTM! Comprehensive test coverage for complex MongoDB queries

The test cases effectively validate the preservation of existing conditions and proper handling of nested $and and $or operators, which is crucial for the PR's objective of maintaining filter conditions during pagination.

However, there are some formatting inconsistencies in the TestAndComplexFilter function.

 		"$and": bson.A{
 			bson.M{"x": 10},
 			bson.M{"y": 20},
-		},
+		},
 		"$or": bson.A{
 			bson.M{"a": 1},
 			bson.M{"b": 2},
-		},
+		},

121-175: LGTM! Excellent test case for the pagination cursor issue

This test case effectively validates the fix for the project fetching issue mentioned in the PR objectives. It ensures that the top-level key conditions (team) are preserved when combining with pagination cursor conditions.

A few suggestions to improve the test:

  1. Consider using more descriptive variable names:
-	team := "team_id_example"
-	last := "last_project_id"
-	updatedat := 1654849072592
+	teamID := "team_id_example"
+	lastProjectID := "last_project_id"
+	lastUpdatedTimestamp := 1654849072592
  1. Consider adding a comment explaining the test scenario and how it relates to the pagination cursor issue.
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 08c9573 and 0b2a88e.

📒 Files selected for processing (2)
  • mongox/util.go (2 hunks)
  • mongox/util_test.go (2 hunks)
🔇 Additional comments (4)
mongox/util.go (1)

83-84: Verify the key preservation behavior.

This is the critical fix for the pagination cursor issue. Let's verify it works as expected across different scenarios.

✅ Verification successful

Let me analyze the code further to verify the key preservation behavior.


Key preservation behavior is correctly implemented

The implementation correctly preserves existing keys and handles pagination filters as expected:

  • If a key already exists in the filter, the original filter is returned unchanged (lines 83-84)
  • For pagination (empty key case), the condition is added to $and array without wrapping
  • The isEmptyCondition helper properly validates empty conditions across all BSON types
  • Test coverage confirms the behavior across various scenarios including pagination filters
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the usage of And function with key preservation
# Look for test cases and actual usage patterns

# Check test coverage
rg -A 5 "TestAnd.*" mongox/

# Look for actual usage patterns
rg -A 5 "And\(" --type go

Length of output: 4830


Script:

#!/bin/bash
# Get the full implementation of And function and its helper functions
ast-grep --pattern 'func And($$$) $$$'

# Get the full implementation of isEmptyCondition
ast-grep --pattern 'func isEmptyCondition($$$) $$$'

# Look for pagination-related usages
rg -B 5 -A 5 'And\(' mongox/pagination.go

Length of output: 2185

mongox/util_test.go (3)

19-39: LGTM! Well-structured test cases for basic scenarios

The test cases effectively validate the And function's behavior with empty filters and empty keys. The assertions properly verify the BSON structure maintenance.


103-119: LGTM! Good coverage of edge cases

The test cases properly validate the handling of nil filters and empty slice conditions, which helps prevent potential runtime issues.


Line range hint 1-175: Verify the fix with integration tests

While the unit tests comprehensively cover the And function's behavior, it would be beneficial to verify the fix with integration tests that simulate the actual project fetching scenario with pagination.

mongox/util.go Outdated
Comment on lines 71 to 213
func And(filter interface{}, key string, condition interface{}) interface{} {
if condition == nil || isEmptyCondition(condition) {
return filter
}

if key != "" && GetE(filter, key) != nil {
return filter
}
var g interface{}
if key == "" {
g = f
} else {
g = bson.M{key: f}
}
if GetE(filter, "$or") != nil {
return bson.M{
"$and": []interface{}{filter, g},
}
filterMap, ok := filter.(bson.M)
if !ok || len(filterMap) == 0 {
filterMap = bson.M{}
}
if and := GetE(filter, "$and"); and != nil {
return bson.M{
"$and": AppendI(and, g),

var newCondition interface{}
if key != "" {
if _, exists := filterMap[key]; exists {
return filter
}
newCondition = bson.M{key: condition}
} else {
newCondition = condition
}
if key == "" {
return bson.M{
"$and": []interface{}{filter, g},
}

if existingAnd, ok := filterMap["$and"].(bson.A); ok {
filterMap["$and"] = append(existingAnd, newCondition)
} else {
filterMap["$and"] = bson.A{newCondition}
}
return AppendE(filter, bson.E{Key: key, Value: f})
return filterMap
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Document the function and highlight the key filter preservation.

The implementation correctly addresses the pagination cursor issue by preserving existing key filters. However, some improvements would enhance maintainability:

+// And combines a filter with a new condition using MongoDB's $and operator.
+// If key is provided, it checks if the key already exists in the filter to preserve
+// top-level key conditions (important for pagination cursor handling).
+// Returns:
+// - original filter if condition is empty or key already exists
+// - new filter with condition added to $and array otherwise
 func And(filter interface{}, key string, condition interface{}) interface{} {
 	if condition == nil || isEmptyCondition(condition) {
 		return filter
 	}
 
 	filterMap, ok := filter.(bson.M)
 	if !ok || len(filterMap) == 0 {
 		filterMap = bson.M{}
 	}
 
 	var newCondition interface{}
 	if key != "" {
+		// Preserve existing key filter to prevent cursor from overriding top-level conditions
 		if _, exists := filterMap[key]; exists {
 			return filter
 		}
 		newCondition = bson.M{key: condition}
 	} else {
 		newCondition = condition
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func And(filter interface{}, key string, condition interface{}) interface{} {
if condition == nil || isEmptyCondition(condition) {
return filter
}
if key != "" && GetE(filter, key) != nil {
return filter
}
var g interface{}
if key == "" {
g = f
} else {
g = bson.M{key: f}
}
if GetE(filter, "$or") != nil {
return bson.M{
"$and": []interface{}{filter, g},
}
filterMap, ok := filter.(bson.M)
if !ok || len(filterMap) == 0 {
filterMap = bson.M{}
}
if and := GetE(filter, "$and"); and != nil {
return bson.M{
"$and": AppendI(and, g),
var newCondition interface{}
if key != "" {
if _, exists := filterMap[key]; exists {
return filter
}
newCondition = bson.M{key: condition}
} else {
newCondition = condition
}
if key == "" {
return bson.M{
"$and": []interface{}{filter, g},
}
if existingAnd, ok := filterMap["$and"].(bson.A); ok {
filterMap["$and"] = append(existingAnd, newCondition)
} else {
filterMap["$and"] = bson.A{newCondition}
}
return AppendE(filter, bson.E{Key: key, Value: f})
return filterMap
// And combines a filter with a new condition using MongoDB's $and operator.
// If key is provided, it checks if the key already exists in the filter to preserve
// top-level key conditions (important for pagination cursor handling).
// Returns:
// - original filter if condition is empty or key already exists
// - new filter with condition added to $and array otherwise
func And(filter interface{}, key string, condition interface{}) interface{} {
if condition == nil || isEmptyCondition(condition) {
return filter
}
filterMap, ok := filter.(bson.M)
if !ok || len(filterMap) == 0 {
filterMap = bson.M{}
}
var newCondition interface{}
if key != "" {
// Preserve existing key filter to prevent cursor from overriding top-level conditions
if _, exists := filterMap[key]; exists {
return filter
}
newCondition = bson.M{key: condition}
} else {
newCondition = condition
}
if existingAnd, ok := filterMap["$and"].(bson.A); ok {
filterMap["$and"] = append(existingAnd, newCondition)
} else {
filterMap["$and"] = bson.A{newCondition}
}
return filterMap

@hexaforce hexaforce force-pushed the fix/original-key-filter branch from 0b2a88e to 107d45d Compare November 27, 2024 05:09
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (1)
mongox/util_test.go (1)

The test function name TestConvertdToM appears to be a typo

The function DToM is still exported (uppercase) in util.go and is used consistently throughout the codebase. The test function name TestConvertdToM appears to be a typo as it's testing the exported DToM function. The test function name should be TestConvertDToM to match the function it's testing.

  • mongox/util_test.go: Rename TestConvertdToM to TestConvertDToM to match the exported function name
🔗 Analysis chain

Line range hint 10-17: Verify the intention behind renaming TestConvertDToM

The function has been renamed from TestConvertDToM to TestConvertdToM, which suggests that the underlying DToM function might have been made private (renamed to dToM). Please ensure this is intentional and aligns with the API design.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if DToM is still used elsewhere in the codebase
rg "DToM\(" --type go

Length of output: 903


Script:

#!/bin/bash
# Check git history for the test file to see if there's a rename
git log -p mongox/util_test.go | grep -A 5 "^@@.*@@.*func Test"

Length of output: 0


Script:

#!/bin/bash
# Check if the function is exported (used) outside the mongox package
rg "mongox\.DToM\(" --type go

Length of output: 31


Script:

#!/bin/bash
# Check the current implementation in util.go
cat mongox/util.go

Length of output: 1901

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0b2a88e and 107d45d.

📒 Files selected for processing (2)
  • mongox/util.go (2 hunks)
  • mongox/util_test.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • mongox/util.go
🔇 Additional comments (2)
mongox/util_test.go (2)

19-119: Well-structured test coverage for And function!

The test suite comprehensively covers various scenarios:

  • Empty and nil filters
  • Empty keys
  • Existing $and conditions
  • Complex nested conditions with $or
  • Edge cases like empty slice conditions

This thorough coverage will help ensure the robustness of the And function.


121-175: Excellent test case for validating the PR's core objective!

This test case effectively validates that the original filter conditions (team, deleted, coresupport) are preserved when adding pagination conditions. This directly addresses the reported issue where the pagination cursor was taking precedence over top-level key conditions.

The test ensures:

  1. Team-specific filtering remains intact
  2. Proper handling of pagination using both updatedat and id fields
  3. Preservation of deleted and coresupport flag conditions

This test will help prevent regression of the fixed issue.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (5)
mongox/util.go (2)

5-23: Add documentation for the new utility function.

The isEmptyCondition function should be documented to explain its purpose and return values. This is especially important as it's used in a critical path for handling MongoDB queries.

Add this documentation:

+// isEmptyCondition checks if a MongoDB condition is empty based on its type.
+// It supports various BSON types (M, D, A) and their slice variants.
+// Returns true if the condition is empty (has no elements), false otherwise.
 func isEmptyCondition(condition interface{}) bool {

76-102: Add error handling for edge cases in condition merging.

The current implementation assumes all BSON type conversions will succeed. Consider adding error handling for the following edge cases:

  1. Invalid BSON types in existing conditions
  2. Type conversion failures during merging

Here's a suggested improvement:

 func And(filter interface{}, key string, condition interface{}) interface{} {
     if condition == nil || isEmptyCondition(condition) {
         return filter
     }
 
     filterMap, ok := filter.(bson.M)
     if !ok || len(filterMap) == 0 {
         filterMap = bson.M{}
     }
 
     var newCondition interface{}
     if key != "" {
         if _, exists := filterMap[key]; exists {
             return filter
         }
         newCondition = bson.M{key: condition}
     } else {
         newCondition = condition
     }
 
+    // Validate that newCondition is a valid BSON type
+    if !isValidBSONType(newCondition) {
+        return filter
+    }
+
     if existingAnd, ok := filterMap["$and"].(bson.A); ok {
+        // Validate existing conditions
+        for _, cond := range existingAnd {
+            if !isValidBSONType(cond) {
+                return filter
+            }
+        }
         filterMap["$and"] = append(existingAnd, newCondition)
     } else {
         existingConditions := make(bson.A, 0)
         for k, v := range filterMap {
             if k != "$and" {
+                if !isValidBSONType(v) {
+                    return filter
+                }
                 existingConditions = append(existingConditions, bson.M{k: v})
             }
         }
         filterMap["$and"] = append(existingConditions, newCondition)
     }
     return filterMap
 }
+
+// isValidBSONType checks if the given value is a valid BSON type
+func isValidBSONType(v interface{}) bool {
+    switch v.(type) {
+    case bson.M, bson.D, bson.A, []bson.M, []bson.D, []bson.A, []interface{}:
+        return true
+    default:
+        return false
+    }
+}
mongox/util_test.go (3)

Line range hint 10-17: Revert function name to follow Go naming conventions

The function name should be TestConvertDToM instead of TestConvertdToM to follow Go naming conventions where acronyms should be uppercase (D for Document, M for Map).


130-184: Excellent test case for the pagination cursor issue

This test case directly validates the fix for the main issue by ensuring that:

  1. The team filter is preserved when adding pagination conditions
  2. Complex conditions (deleted, coresupport) remain intact
  3. Cursor-based pagination conditions are correctly applied

Consider adding test cases for:

  1. Multiple workspace scenarios (>16 workspaces as mentioned in PR)
  2. Different cursor positions (middle, end of the list)
  3. Edge cases with maximum number of items

Line range hint 1-184: Strong test coverage that validates the fix

The test suite effectively validates the fix for the pagination cursor issue while maintaining good testing practices:

  1. Comprehensive coverage from basic to complex scenarios
  2. Clear test organization and naming
  3. Direct validation of the PR's objective

Consider extracting common test data (like team_id, updatedat) into test fixtures or helper functions to improve maintainability and reusability across tests.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 107d45d and 805ec6e.

📒 Files selected for processing (2)
  • mongox/util.go (2 hunks)
  • mongox/util_test.go (2 hunks)
🔇 Additional comments (5)
mongox/util.go (2)

71-71: Document the function and highlight the key filter preservation.

The implementation correctly addresses the pagination cursor issue by preserving existing key filters. Adding documentation would improve maintainability.


71-102: Verify the fix with pagination cursor scenarios.

The implementation looks correct, but let's verify it handles all pagination scenarios correctly.

✅ Verification successful

Based on the search results, I can now verify the fix. The code shows that pagination is implemented correctly with cursor-based navigation in mongox/pagination.go. The key findings that verify the fix are:

  1. The And function in mongox/util.go properly preserves existing conditions when merging new ones
  2. The pagination implementation in mongox/pagination.go correctly handles cursor scenarios by:
    • Properly building cursor-based queries with $gt/$lt operators
    • Maintaining sort order with bson.M{"$sort": sortFilter(p, s)}
    • Preserving existing filters when adding cursor conditions
    • Properly handling both forward (After) and backward (Before) pagination

The fix correctly handles pagination cursor scenarios and preserves filter conditions.

The implementation ensures that:

  • Top-level conditions are preserved when cursor conditions are added
  • Sort order is maintained during pagination
  • Cursor-based navigation works correctly in both directions
  • Filter conditions are properly merged using the $and operator
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for pagination cursor usage to verify the fix's impact

# Look for pagination-related query patterns
rg -A 5 'cursor|pagination|limit|skip' --type go

# Look for MongoDB query building patterns
ast-grep --pattern 'bson.M{$_: $_}'

Length of output: 37249

mongox/util_test.go (3)

19-58: Well-structured test cases for core functionality

The test cases effectively cover the basic scenarios for the And function:

  • Empty filter handling
  • Empty key handling
  • Appending to existing $and conditions

These tests help ensure that the original key filter is maintained, which directly addresses the PR objective.


61-110: Critical test cases for filter preservation

These test cases are essential for validating the fix for the pagination cursor issue:

  • TestAndWithOrAndEmptyKey ensures that $or conditions are preserved when adding new conditions
  • TestAndComplexFilter verifies that complex nested conditions remain intact

This directly addresses the PR objective of preventing the cursor from taking precedence over top-level key conditions.


112-128: Good coverage of edge cases

The edge case tests ensure robust handling of:

  • Nil filters
  • Empty slice conditions

This helps prevent potential runtime issues when dealing with undefined or empty conditions.

@hexaforce hexaforce force-pushed the fix/original-key-filter branch from 21f1beb to d38d000 Compare November 27, 2024 06:24
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (5)
mongox/util.go (3)

161-180: LGTM! Consider adding documentation.

The implementation correctly handles all BSON types and their slice variants. The default case appropriately returns false for non-empty conditions.

Add documentation to explain the function's purpose:

+// isEmptyCondition checks if a BSON condition is empty by examining its length.
+// Returns true for nil or empty BSON types (M, D, A) and their slice variants.
+// Returns false for non-empty conditions and unsupported types.
 func isEmptyCondition(condition interface{}) bool {

182-214: LGTM! Add comprehensive documentation.

The implementation correctly addresses the pagination cursor issue by preserving existing key filters and properly handling the $and operator.

Add detailed documentation to explain the function's behavior:

+// AddCondition adds a new condition to a MongoDB filter while preserving existing conditions.
+// If a key is provided and already exists in the filter, the original filter is returned unchanged.
+// The function consolidates conditions using MongoDB's $and operator, maintaining both existing
+// and new conditions. This is particularly important for pagination scenarios where cursor-based
+// conditions should not override top-level key filters.
+//
+// Parameters:
+//   - filter: existing MongoDB filter (can be nil or empty)
+//   - key: optional field key for the condition
+//   - condition: the new condition to add
+//
+// Returns:
+//   - modified filter with the new condition added via $and operator
 func AddCondition(filter interface{}, key string, condition interface{}) interface{} {

187-190: Consider adding type assertion error handling.

The type assertion to bson.M could fail silently. Consider adding explicit error handling for unsupported filter types.

-	filterMap, ok := filter.(bson.M)
-	if !ok || len(filterMap) == 0 {
-		filterMap = bson.M{}
-	}
+	var filterMap bson.M
+	switch f := filter.(type) {
+	case bson.M:
+		if len(f) > 0 {
+			filterMap = f
+		} else {
+			filterMap = bson.M{}
+		}
+	case bson.D:
+		// Convert bson.D to bson.M
+		filterMap = make(bson.M, len(f))
+		for _, e := range f {
+			filterMap[e.Key] = e.Value
+		}
+	default:
+		filterMap = bson.M{}
+	}
mongox/util_test.go (2)

205-210: Consider adding test cases for edge conditions

The empty slice condition tests are good, but consider adding more edge cases:

  1. Test with nil slice
  2. Test with slice containing nil elements
  3. Test with empty map condition
  4. Test with invalid BSON types

Also applies to: 373-378


169-192: Improve test readability by using helper functions

The complex filter test cases contain deeply nested BSON structures that are hard to read. Consider creating helper functions to build these test structures.

Example:

func buildComplexFilter() bson.M {
    return bson.M{
        "$and": bson.A{
            bson.M{"x": 10},
            bson.M{"y": 20},
        },
        "$or": bson.A{
            bson.M{"a": 1},
            bson.M{"b": 2},
        },
    }
}

func TestAddConditionComplexFilter(t *testing.T) {
    filter := buildComplexFilter()
    expected := buildComplexFilter()
    expected["$and"] = append(expected["$and"].(bson.A), bson.M{"c": bson.M{"d": 3}})
    
    actual := AddCondition(filter, "c", bson.M{"d": 3})
    assert.Equal(t, expected, actual)
}

Also applies to: 337-360

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 805ec6e and d38d000.

📒 Files selected for processing (2)
  • mongox/util.go (1 hunks)
  • mongox/util_test.go (1 hunks)
🔇 Additional comments (2)
mongox/util.go (1)

Line range hint 1-159: Verify the safe removal of deprecated functions.

The AI summary indicates that AppendE, GetE, and AppendI functions will be removed. Let's verify that all their use cases are covered by the new implementation.

mongox/util_test.go (1)

212-267: Good test coverage for the pagination cursor issue

The TestAndProjectRefetchFilter function effectively tests the scenario described in the PR objectives where a pagination cursor is present. It verifies that:

  1. The team filter is preserved
  2. The cursor conditions (updatedat and id) are correctly added to the $and array
  3. The existing conditions for deleted and coresupport fields are maintained

Comment on lines 101 to 435

func TestAddConditionComplexFilter(t *testing.T) {
filter := bson.M{
"$and": bson.A{
bson.M{"x": 10},
bson.M{"y": 20},
},
"$or": bson.A{
bson.M{"a": 1},
bson.M{"b": 2},
},
}
expected := bson.M{
"$and": bson.A{
bson.M{"x": 10},
bson.M{"y": 20},
bson.M{"c": bson.M{"d": 3}},
},
"$or": bson.A{bson.M{"a": 1},
bson.M{"b": 2},
},
}
actual := AddCondition(filter, "c", bson.M{"d": 3})
assert.Equal(t, expected, actual)
}

func TestAddConditionNilFilter(t *testing.T) {
var filter interface{}
expected := bson.M{
"$and": bson.A{
bson.M{"b": bson.M{"c": 2}},
},
}
actual := AddCondition(filter, "b", bson.M{"c": 2})
assert.Equal(t, expected, actual)
}

func TestAddConditionEmptySliceCondition(t *testing.T) {
filter := bson.M{"a": 1}
expected := bson.M{"a": 1}
actual := AddCondition(filter, "b", bson.A{})
assert.Equal(t, expected, actual)
}

func TestAddConditionProjectRefetchFilter(t *testing.T) {
team := "team_id_example"
last := "last_project_id"
updatedat := 1654849072592
filter := bson.M{
"$and": bson.A{
bson.M{
"$or": bson.A{
bson.M{"deleted": false},
bson.M{"deleted": bson.M{"$exists": false}},
},
},
bson.M{
"$or": bson.A{
bson.M{"coresupport": true},
bson.M{"coresupport": bson.M{"$exists": false}},
},
},
},
"team": team,
}

condition := bson.M{
"$or": bson.A{
bson.M{"updatedat": bson.M{"$lt": updatedat}},
bson.M{
"id": bson.M{"$lt": last},
"updatedat": updatedat,
},
},
}

expected := bson.M{
"$and": bson.A{
bson.M{"$or": bson.A{
bson.M{"deleted": false},
bson.M{"deleted": bson.M{"$exists": false}},
},
},
bson.M{"$or": bson.A{
bson.M{"coresupport": true},
bson.M{"coresupport": bson.M{"$exists": false}},
},
},
bson.M{"$or": bson.A{
bson.M{"updatedat": bson.M{"$lt": updatedat}},
bson.M{"id": bson.M{"$lt": last}, "updatedat": updatedat},
},
},
},
"team": team,
}

actual := AddCondition(filter, "", condition)
assert.Equal(t, expected, actual)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Reduce test duplication by consolidating identical test cases

There are multiple pairs of identical test functions with different names:

  • TestAndEmptyFilter and TestAddConditionEmptyFilter
  • TestAndEmptyKey and TestAddConditionEmptyKey
  • TestAndExistingAddCondition and TestAddConditionExistingAddCondition
  • TestAndWithOrAndEmptyKey and TestAddConditionWithOrAndEmptyKey
  • TestAndComplexFilter and TestAddConditionComplexFilter
  • TestAndNilFilter and TestAddConditionNilFilter
  • TestAndEmptySliceCondition and TestAddConditionEmptySliceCondition
  • TestAndProjectRefetchFilter and TestAddConditionProjectRefetchFilter

Consider consolidating these duplicate tests into a single set of test functions using table-driven tests. Here's an example refactor:

-func TestAndEmptyFilter(t *testing.T) {
-    filter := bson.M{}
-    expected := bson.M{
-        "$and": bson.A{
-            bson.M{"b": bson.M{"c": 2}},
-        },
-    }
-    actual := AddCondition(filter, "b", bson.M{"c": 2})
-    assert.Equal(t, expected, actual)
-}
-
-func TestAddConditionEmptyFilter(t *testing.T) {
-    filter := bson.M{}
-    expected := bson.M{
-        "$and": bson.A{
-            bson.M{"b": bson.M{"c": 2}},
-        },
-    }
-    actual := AddCondition(filter, "b", bson.M{"c": 2})
-    assert.Equal(t, expected, actual)
-}
+func TestAddCondition(t *testing.T) {
+    tests := []struct {
+        name      string
+        filter    interface{}
+        key       string
+        condition interface{}
+        expected  bson.M
+    }{
+        {
+            name:      "empty filter",
+            filter:    bson.M{},
+            key:       "b",
+            condition: bson.M{"c": 2},
+            expected: bson.M{
+                "$and": bson.A{
+                    bson.M{"b": bson.M{"c": 2}},
+                },
+            },
+        },
+        // Add other test cases here
+    }
+
+    for _, tt := range tests {
+        t.Run(tt.name, func(t *testing.T) {
+            actual := AddCondition(tt.filter, tt.key, tt.condition)
+            assert.Equal(t, tt.expected, actual)
+        })
+    }
+}

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between d38d000 and 5d9562a.

📒 Files selected for processing (1)
  • mongox/pagination.go (2 hunks)

filter = AddCondition(rawFilter, "", pFilter)
}

return c.paginate(ctx, rawFilter, s, p, filter, consumer)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Potential mismatch in document count due to rawFilter usage

In PaginateProject, you're passing rawFilter to the paginate method. Since filter may have added conditions (like pagination filters), using rawFilter for counting documents can result in an inaccurate count that doesn't reflect the actual query.

Consider updating the call to use filter:

-return c.paginate(ctx, rawFilter, s, p, filter, consumer)
+return c.paginate(ctx, filter, s, p, filter, consumer)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return c.paginate(ctx, rawFilter, s, p, filter, consumer)
return c.paginate(ctx, filter, s, p, filter, consumer)

mongox/pagination.go Show resolved Hide resolved
hasNextPage, hasPreviousPage := pageInfo(p, hasMore)

return usecasex.NewPageInfo(count, startCursor, endCursor, hasNextPage, hasPreviousPage), nil
return c.paginate(ctx, rawFilter, s, p, filter, consumer)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Inconsistent use of rawFilter vs filter when calling paginate

In the Paginate method, you pass rawFilter as the rawFilter argument to c.paginate, while filter may include additional pagination conditions (pFilter). This could lead to inconsistencies during document counting in paginate, as rawFilter doesn't contain these additional conditions.

To ensure consistency between the documents counted and those retrieved, consider passing filter instead of rawFilter:

-return c.paginate(ctx, rawFilter, s, p, filter, consumer)
+return c.paginate(ctx, filter, s, p, filter, consumer)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return c.paginate(ctx, rawFilter, s, p, filter, consumer)
return c.paginate(ctx, filter, s, p, filter, consumer)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (3)
mongox/pagination.go (1)

293-353: LGTM: Well-structured pagination implementation

The pagination helper method is well-implemented with proper:

  • Cursor direction handling
  • Sort key management
  • Error handling
  • Resource cleanup

Consider adding caching for the document count in high-traffic scenarios, as counting documents in MongoDB can be expensive for large collections.

mongox/util_test.go (2)

205-210: Consider adding edge cases

The empty slice condition test is good, but consider adding more edge cases:

  • nil condition
  • Empty map condition
  • Invalid BSON types

169-192: Improve test readability

The complex filter test case could benefit from better formatting and documentation:

  1. Add comments explaining the test scenario
  2. Format the BSON document structure consistently

Apply this diff to improve readability:

 func TestAndComplexFilter(t *testing.T) {
+    // Test adding a condition to a filter with existing $and and $or operators
     filter := bson.M{
         "$and": bson.A{
             bson.M{"x": 10},
             bson.M{"y": 20},
         },
         "$or": bson.A{
             bson.M{"a": 1},
             bson.M{"b": 2},
         },
     }
     expected := bson.M{
         "$and": bson.A{
             bson.M{"x": 10},
             bson.M{"y": 20},
             bson.M{"c": bson.M{"d": 3}},
         },
-        "$or": bson.A{bson.M{"a": 1},
-            bson.M{"b": 2},
+        "$or": bson.A{
+            bson.M{"a": 1},
+            bson.M{"b": 2},
         },
     }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 5d9562a and c623d5b.

📒 Files selected for processing (2)
  • mongox/pagination.go (2 hunks)
  • mongox/util_test.go (1 hunks)
🔇 Additional comments (5)
mongox/pagination.go (3)

30-30: ⚠️ Potential issue

Regression: Using rawFilter instead of filter can lead to incorrect pagination

This change reintroduces a previously identified issue where using rawFilter instead of filter in the paginate call can lead to incorrect document counts and pagination results, as rawFilter doesn't include the pagination conditions.

Apply this fix:

-return c.paginate(ctx, rawFilter, s, p, filter, consumer, opts)
+return c.paginate(ctx, filter, s, p, filter, consumer, opts)

329-332: ⚠️ Potential issue

Critical: Document count should use filtered collection

Using rawFilter for CountDocuments will return an incorrect total count that doesn't reflect the applied filters. This could lead to incorrect pagination metadata and UI issues.

Apply this fix:

-count, err := c.collection.CountDocuments(ctx, rawFilter)
+count, err := c.collection.CountDocuments(ctx, filter)

274-291: LGTM: New PaginateProject method properly preserves filters

The implementation correctly uses AddCondition to preserve the original key filters when applying pagination conditions, which addresses the workspace filtering issue mentioned in the PR objectives.

Let's verify the behavior with different filter combinations:

✅ Verification successful

Based on the results from our shell script executions, I can now generate the final response:

Verified: PaginateProject correctly implements filter preservation

The implementation is correct and consistent with the codebase:

  • AddCondition is properly implemented with extensive test coverage for various filter scenarios
  • The method correctly uses AddCondition instead of And for combining filters, which preserves the original key filters as intended
  • The empty key usage in AddCondition(rawFilter, "", pFilter) is validated by test cases showing it properly merges conditions while maintaining existing filters
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify AddCondition usage in the codebase
# Expected: AddCondition should be used consistently for filter preservation

# Check if AddCondition is used consistently across pagination methods
rg -A 5 "AddCondition.*filter.*pFilter" 

# Check for any remaining uses of And that might need migration
rg -A 5 "And.*filter.*pFilter"

Length of output: 74


Script:

#!/bin/bash
# Let's try a broader search to understand the usage of AddCondition and filter handling

# Check for AddCondition function definition and usage
rg -A 10 "func.*AddCondition"

# Check all occurrences of AddCondition calls
rg "AddCondition\("

# Look for filter handling in pagination-related code
rg -A 5 "filter.*paginate"

# Check for any other pagination methods
ast-grep --pattern 'func $_ Paginate$$$($$$) $$$'

Length of output: 6014


Script:

#!/bin/bash
# Let's check the implementation of paginate method and other pagination-related methods

# Check paginate method implementation
ast-grep --pattern 'func $_ paginate($$$) $$$'

# Look for all pagination-related methods in Collection
ast-grep --pattern 'func (c *Collection) $$$Paginate$$$($$$) $$$'

# Check for any And function usage in pagination context
rg -B 5 -A 5 "func.*And\("

Length of output: 1296

mongox/util_test.go (2)

212-264: Test case aligns with PR objectives

The TestAndProjectRefetchFilter test case effectively validates the fix for the pagination cursor issue mentioned in the PR objectives. It ensures that the top-level key conditions (team, deleted, coresupport) are preserved when adding pagination conditions.


101-433: 🛠️ Refactor suggestion

Consolidate duplicate test functions

The following pairs of test functions are identical:

  • TestAndEmptyFilter and TestAddConditionEmptyFilter
  • TestAndEmptyKey and TestAddConditionEmptyKey
  • TestAndExistingAddCondition and TestAddConditionExistingAddCondition
  • TestAndWithOrAndEmptyKey and TestAddConditionWithOrAndEmptyKey
  • TestAndComplexFilter and TestAddConditionComplexFilter
  • TestAndNilFilter and TestAddConditionNilFilter
  • TestAndEmptySliceCondition and TestAddConditionEmptySliceCondition
  • TestAndProjectRefetchFilter and TestAddConditionProjectRefetchFilter

Consider consolidating these duplicate tests into a single set using table-driven tests. Here's an example refactor:

-func TestAndEmptyFilter(t *testing.T) {
-    filter := bson.M{}
-    expected := bson.M{
-        "$and": bson.A{
-            bson.M{"b": bson.M{"c": 2}},
-        },
-    }
-    actual := AddCondition(filter, "b", bson.M{"c": 2})
-    assert.Equal(t, expected, actual)
-}
+func TestAddCondition(t *testing.T) {
+    tests := []struct {
+        name      string
+        filter    interface{}
+        key       string
+        condition interface{}
+        expected  bson.M
+    }{
+        {
+            name:      "empty filter",
+            filter:    bson.M{},
+            key:       "b",
+            condition: bson.M{"c": 2},
+            expected: bson.M{
+                "$and": bson.A{
+                    bson.M{"b": bson.M{"c": 2}},
+                },
+            },
+        },
+        // Add other test cases here
+    }
+
+    for _, tt := range tests {
+        t.Run(tt.name, func(t *testing.T) {
+            actual := AddCondition(tt.filter, tt.key, tt.condition)
+            assert.Equal(t, tt.expected, actual)
+        })
+    }
+}

Likely invalid or redundant comment.

@pyshx pyshx merged commit 4fcdd23 into main Nov 27, 2024
2 checks passed
@pyshx pyshx deleted the fix/original-key-filter branch November 27, 2024 09:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants