Skip to content

Commit

Permalink
added single field "like" filtering using the ~ character along with …
Browse files Browse the repository at this point in the history
…a unit test and an update to the README.md that details all supported filter operators (#13)
  • Loading branch information
jmachen authored Aug 26, 2024
1 parent ba03094 commit 60b35df
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 1 deletion.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ Any filter combination can be used here `filter.PAGINATION|filter.ORDER_BY` e.g.
curl -X GET http://localhost:8080/users?page=1&limit=10&order_by=username&order_direction=asc&filter="name:John"
```

## Supported filter operators
- : The equality operator `filter=username:John` matches only when the username is exactly `John`
- \> The greater than operator `filter=age>35` matches only when age is more than 35
- \< The less than operator `filter=salary<80000` matches only when salary is less than 80,000
- \>= The greater than or equals to operator `filter=items>=100` matches only when items is at least 100
- \<= The less than or equals to operator `filter=score<=100000` matches when score is 100,000 or lower
- \!= The not equals to operator `state!=FAIL` matches when state has any value other than FAIL
- \~ The like operator `filter=lastName~illi` matches when lastName contains the substring `illi`

## TODO list
- [x] Write tests for the lib with CI integration
- [x] Add support for case-insensitive search
Expand Down
4 changes: 3 additions & 1 deletion gin-gorm-filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func filterField(field reflect.StructField, phrase string) clause.Expression {
// re, err := regexp.Compile(fmt.Sprintf(`(?m)%v([:<>!=]{1,2})(\w{1,}).*`, paramName))
// for the current regex, the compound operators (such as >=) must come before the
// single operators (such as <) or they will be incorrectly identified
re, err := regexp.Compile(fmt.Sprintf(`(?m)%v(:|!=|>=|<=|>|<)([^,]*).*`, paramName))
re, err := regexp.Compile(fmt.Sprintf(`(?m)%v(:|!=|>=|<=|>|<|~)([^,]*).*`, paramName))
if err != nil {
return nil
}
Expand All @@ -121,6 +121,8 @@ func filterField(field reflect.StructField, phrase string) clause.Expression {
return clause.Gt{Column: columnName, Value: filterSubPhraseMatch[2]}
case "<":
return clause.Lt{Column: columnName, Value: filterSubPhraseMatch[2]}
case "~":
return clause.Like{Column: columnName, Value: filterSubPhraseMatch[2]}
default:
return clause.Eq{Column: columnName, Value: filterSubPhraseMatch[2]}
}
Expand Down
17 changes: 17 additions & 0 deletions gin-gorm-filter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,23 @@ func (s *TestSuite) TestFiltersBasic() {
s.NoError(err)
}

// TestFiltersBasic is a test for basic filters functionality.
func (s *TestSuite) TestFiltersLike() {
var users []User
ctx := gin.Context{}
ctx.Request = &http.Request{
URL: &url.URL{
RawQuery: "filter=login~samp",
},
}

s.mock.ExpectQuery(`^SELECT \* FROM "users" WHERE "Username" LIKE \$1 ORDER BY "id" DESC LIMIT \$2$`).
WithArgs("samp", 10).
WillReturnRows(sqlmock.NewRows([]string{"id", "Username", "FullName", "Email", "Password"}))
err := s.db.Model(&User{}).Scopes(FilterByQuery(&ctx, ALL)).Find(&users).Error
s.NoError(err)
}

// Filtering for a field that is not filtered should not be performed
func (s *TestSuite) TestFiltersNotFilterable() {
var users []User
Expand Down

0 comments on commit 60b35df

Please sign in to comment.