Documentation
¶
Overview ¶
Package filter provides utilities for filtering, sorting, and paginating data sets.
Index ¶
- func ApplyPresetConditions(db *gorm.DB, conditions any) *gorm.DB
- func Sanitize(input string) string
- type DataType
- type FieldFilter
- type GolangFilteringConfig
- type Handler
- func (f *Handler[T]) DataGorm(db *gorm.DB, filterRoot Root, pageIndex int, pageSize int) (*PaginationResult[T], error)
- func (f *Handler[T]) DataGormNoPage(db *gorm.DB, filterRoot Root) ([]*T, error)
- func (f *Handler[T]) DataGormNoPageWithPreset(db *gorm.DB, presetConditions any, filterRoot Root) ([]*T, error)
- func (f *Handler[T]) DataGormWithPreset(db *gorm.DB, presetConditions any, filterRoot Root, pageIndex int, ...) (*PaginationResult[T], error)
- func (f *Handler[T]) DataHybridNoPage(db *gorm.DB, threshold int, filterRoot Root) ([]*T, error)
- func (f *Handler[T]) DataQuery(data []*T, filterRoot Root, pageIndex int, pageSize int) (*PaginationResult[T], error)
- func (f *Handler[T]) DataQueryNoPage(data []*T, filterRoot Root) ([]*T, error)
- func (f *Handler[T]) DataQueryNoPageCSV(data []*T, filterRoot Root) ([]byte, error)
- func (f *Handler[T]) DataQueryNoPageCSVCustom(data []*T, filterRoot Root, customGetter func(*T) map[string]any) ([]byte, error)
- func (h *Handler[T]) ExportGetters() map[string]func(*T) any
- func (f *Handler[T]) GormNoPaginationCSV(db *gorm.DB, filterRoot Root) ([]byte, error)
- func (f *Handler[T]) GormNoPaginationCSVCustom(db *gorm.DB, filterRoot Root, customGetter func(*T) map[string]any) ([]byte, error)
- func (f *Handler[T]) GormNoPaginationCSVCustomWithPreset(db *gorm.DB, presetConditions any, filterRoot Root, ...) ([]byte, error)
- func (f *Handler[T]) GormNoPaginationCSVWithPreset(db *gorm.DB, presetConditions any, filterRoot Root) ([]byte, error)
- func (f *Handler[T]) Hybrid(db *gorm.DB, threshold int, filterRoot Root, pageIndex int, pageSize int) (*PaginationResult[T], error)
- func (f *Handler[T]) HybridCSV(db *gorm.DB, threshold int, filterRoot Root) ([]byte, error)
- func (f *Handler[T]) HybridCSVCustom(db *gorm.DB, threshold int, filterRoot Root, ...) ([]byte, error)
- func (f *Handler[T]) HybridCSVCustomWithPreset(db *gorm.DB, presetConditions any, threshold int, filterRoot Root, ...) ([]byte, error)
- func (f *Handler[T]) HybridCSVWithPreset(db *gorm.DB, presetConditions any, threshold int, filterRoot Root) ([]byte, error)
- type Logic
- type Mode
- type PaginationResult
- type Range
- type RangeDate
- type RangeNumber
- type Root
- type SortField
- type SortOrder
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApplyPresetConditions ¶ added in v1.0.3
ApplyPresetConditions applies struct fields as WHERE conditions to the db query. This is a helper to easily apply preset filters from a struct.
Example usage:
type AccountTag struct {
OrganizationID uint
BranchID uint
}
tag := &AccountTag{OrganizationID: 1, BranchID: 2}
db = filter.ApplyPresetConditions(db, tag)
result, err := handler.DataGorm(db, filterRoot, pageIndex, pageSize)
Types ¶
type DataType ¶
type DataType string
DataType defines the data type being filtered
const ( DataTypeNumber DataType = "number" // Numeric values DataTypeText DataType = "text" // Text/string values DataTypeBool DataType = "bool" // Boolean values DataTypeDate DataType = "date" // Date values DataTypeTime DataType = "time" // Time values )
data type constants define the type of data being filtered
type FieldFilter ¶
type FieldFilter struct {
Field string `json:"field"` // Field name to filter on
Value any `json:"value"` // Value to compare against
Mode Mode `json:"mode"` // Comparison mode
DataType DataType `json:"dataType"` // Data type of the field
}
represents a single filter condition
type GolangFilteringConfig ¶ added in v1.1.0
type GolangFilteringConfig struct {
MaxDepth *int
}
type Handler ¶
type Handler[T any] struct { // contains filtered or unexported fields }
Handler is the main struct that handles filtering operations for a specific data type T.
func NewFilter ¶
func NewFilter[T any](config GolangFilteringConfig) *Handler[T]
NewFilter creates a new filter handler that automatically generates getters using reflection WARNING: Higher MaxDepth values (>3) can cause significant memory usage and performance issues with deeply nested or circular struct references. Default is 1 (no nested fields). Getters are cached globally to prevent regeneration for the same type.
func (*Handler[T]) DataGorm ¶
func (f *Handler[T]) DataGorm( db *gorm.DB, filterRoot Root, pageIndex int, pageSize int, ) (*PaginationResult[T], error)
DataGorm performs database-level filtering using GORM queries. It generates SQL WHERE clauses based on the filter configuration and returns paginated results. The db parameter can have existing WHERE conditions (e.g., organization_id, branch_id), and DataGorm will apply additional filters from filterRoot on top of those.
Example with preset conditions using struct:
type AccountTag struct {
OrganizationID uint
BranchID uint
}
tag := &AccountTag{OrganizationID: user.OrganizationID, BranchID: *user.BranchID}
db = filter.ApplyPresetConditions(db, tag)
result, err := handler.DataGorm(db, filterRoot, pageIndex, pageSize)
Example with preset conditions using Where:
presetDB := db.Where("organization_id = ? AND branch_id = ?", orgID, branchID)
result, err := handler.DataGorm(presetDB, filterRoot, pageIndex, pageSize)
func (*Handler[T]) DataGormNoPage ¶ added in v1.2.0
DataGormNoPage performs database-level filtering using GORM queries without pagination. It generates SQL WHERE clauses based on the filter configuration and returns all matching results as a simple array. The db parameter can have existing WHERE conditions (e.g., organization_id, branch_id), and DataGormNoPage will apply additional filters from filterRoot on top of those.
Example with preset conditions using struct:
type AccountTag struct {
OrganizationID uint
BranchID uint
}
tag := &AccountTag{OrganizationID: user.OrganizationID, BranchID: *user.BranchID}
db = filter.ApplyPresetConditions(db, tag)
results, err := handler.DataGormNoPage(db, filterRoot)
Example with preset conditions using Where:
presetDB := db.Where("organization_id = ? AND branch_id = ?", orgID, branchID)
results, err := handler.DataGormNoPage(presetDB, filterRoot)
func (*Handler[T]) DataGormNoPageWithPreset ¶ added in v1.2.0
func (f *Handler[T]) DataGormNoPageWithPreset( db *gorm.DB, presetConditions any, filterRoot Root, ) ([]*T, error)
DataGormNoPageWithPreset is a convenience method that combines ApplyPresetConditions and DataGormNoPage. It accepts preset conditions as a struct and applies them before filtering, returning results without pagination.
Example usage:
type AccountTag struct {
OrganizationID uint `gorm:"column:organization_id"`
BranchID uint `gorm:"column:branch_id"`
}
tag := &AccountTag{
OrganizationID: user.OrganizationID,
BranchID: *user.BranchID,
}
results, err := handler.DataGormNoPageWithPreset(db, tag, filterRoot)
func (*Handler[T]) DataGormWithPreset ¶ added in v1.0.3
func (f *Handler[T]) DataGormWithPreset( db *gorm.DB, presetConditions any, filterRoot Root, pageIndex int, pageSize int, ) (*PaginationResult[T], error)
DataGormWithPreset is a convenience method that combines ApplyPresetConditions and DataGorm. It accepts preset conditions as a struct and applies them before filtering.
Example usage:
type AccountTag struct {
OrganizationID uint `gorm:"column:organization_id"`
BranchID uint `gorm:"column:branch_id"`
}
tag := &AccountTag{
OrganizationID: user.OrganizationID,
BranchID: *user.BranchID,
}
result, err := handler.DataGormWithPreset(db, tag, filterRoot, pageIndex, pageSize)
func (*Handler[T]) DataHybridNoPage ¶ added in v1.2.0
DataHybridNoPage intelligently chooses between in-memory (DataQueryNoPage) and database (DataGormNoPage) filtering based on estimated table size, returning results without pagination.
IMPORTANT: Respects pre-existing WHERE conditions on the db parameter. - If DataQueryNoPage is chosen (small dataset): fetches data using existing conditions, then filters in-memory - If DataGormNoPage is chosen (large dataset): combines existing conditions with filterRoot filters in SQL
Example with pre-existing conditions:
db := gormDB.Where("organization_id = ? AND branch_id = ?", orgID, branchID)
results, err := handler.DataHybridNoPage(db, 10000, filterRoot)
// DataQueryNoPage path: SELECT * FROM table WHERE organization_id = ? AND branch_id = ? (fetch all, filter in-memory)
// DataGormNoPage path: SELECT * FROM table WHERE organization_id = ? AND branch_id = ? AND [filterRoot conditions]
func (*Handler[T]) DataQuery ¶
func (f *Handler[T]) DataQuery( data []*T, filterRoot Root, pageIndex int, pageSize int, ) (*PaginationResult[T], error)
DataQuery performs in-memory filtering with parallel processing. It filters the provided data slice based on the filter configuration and returns paginated results.
func (*Handler[T]) DataQueryNoPage ¶ added in v1.2.0
DataQueryNoPage performs in-memory filtering with parallel processing without pagination. It filters the provided data slice based on the filter configuration and returns all matching results as a simple array.
func (*Handler[T]) DataQueryNoPageCSV ¶ added in v1.2.1
DataQueryNoPageCSV performs in-memory filtering with parallel processing and returns results as CSV bytes. It filters the provided data slice based on the filter configuration and exports all matching results as CSV format. Field names are automatically used as CSV headers.
func (*Handler[T]) DataQueryNoPageCSVCustom ¶ added in v1.2.2
func (f *Handler[T]) DataQueryNoPageCSVCustom( data []*T, filterRoot Root, customGetter func(*T) map[string]any, ) ([]byte, error)
DataQueryNoPageCSVCustom performs in-memory filtering with parallel processing and returns results as CSV bytes. It uses a custom callback function to allow users to define exactly what fields and values to include in the CSV output. This provides full control over CSV structure and field mapping on the user side.
Parameters:
- data: slice of pointers to the data type T to filter
- filterRoot: filter configuration defining conditions, logic, and sorting
- customGetter: callback function that takes a data item and returns a map[string]any where keys are column headers and values are the corresponding data
Returns CSV bytes with headers from the customGetter map keys, sorted alphabetically for deterministic ordering.
Example usage:
csvData, err := handler.DataQueryNoPageCSVCustom(users, filterRoot, func(user *User) map[string]any {
return map[string]any{
"Full Name": user.FirstName + " " + user.LastName,
"Email": user.Email,
"Status": user.IsActive,
"Department": user.Department.Name, // Access nested fields
}
})
func (*Handler[T]) ExportGetters ¶ added in v1.2.7
ExportGetters returns the getters map for inspection/debugging
func (*Handler[T]) GormNoPaginationCSV ¶ added in v1.2.1
GormNoPaginationCSV performs database-level filtering using GORM queries and returns results as CSV bytes. It generates SQL WHERE clauses based on the filter configuration and exports all matching results as CSV format. Field names are automatically used as CSV headers. The db parameter can have existing WHERE conditions (e.g., organization_id, branch_id), and GormNoPaginationCSV will apply additional filters from filterRoot on top of those.
Example with preset conditions using struct:
type AccountTag struct {
OrganizationID uint
BranchID uint
}
tag := &AccountTag{OrganizationID: user.OrganizationID, BranchID: *user.BranchID}
db = filter.ApplyPresetConditions(db, tag)
csvData, err := handler.GormNoPaginationCSV(db, filterRoot)
Example with preset conditions using Where:
presetDB := db.Where("organization_id = ? AND branch_id = ?", orgID, branchID)
csvData, err := handler.GormNoPaginationCSV(presetDB, filterRoot)
func (*Handler[T]) GormNoPaginationCSVCustom ¶ added in v1.2.2
func (f *Handler[T]) GormNoPaginationCSVCustom( db *gorm.DB, filterRoot Root, customGetter func(*T) map[string]any, ) ([]byte, error)
GormNoPaginationCSVCustom performs database-level filtering and returns results as CSV bytes. It uses a custom callback function to allow users to define exactly what fields and values to include in the CSV output. This provides full control over CSV structure and field mapping on the user side.
Parameters:
- db: GORM database instance with any preset conditions
- filterRoot: filter configuration defining conditions, logic, and sorting
- customGetter: callback function that takes a data item and returns a map[string]any where keys are column headers and values are the corresponding data
Returns CSV bytes with headers from the customGetter map keys, sorted alphabetically for deterministic ordering.
Example usage:
csvData, err := handler.GormNoPaginationCSVCustom(db, filterRoot, func(user *User) map[string]any {
return map[string]any{
"Full Name": user.FirstName + " " + user.LastName,
"Email": user.Email,
"Status": user.IsActive,
"Department": user.Department.Name, // Access nested fields if preloaded
}
})
func (*Handler[T]) GormNoPaginationCSVCustomWithPreset ¶ added in v1.2.2
func (f *Handler[T]) GormNoPaginationCSVCustomWithPreset( db *gorm.DB, presetConditions any, filterRoot Root, customGetter func(*T) map[string]any, ) ([]byte, error)
GormNoPaginationCSVCustomWithPreset is a convenience method that combines preset conditions with GormNoPaginationCSVCustom. It applies preset conditions to the database query before filtering and CSV export using a custom getter function.
Parameters:
- db: GORM database instance
- presetConditions: struct or map with preset WHERE conditions to apply before filtering
- filterRoot: filter configuration defining conditions, logic, and sorting
- customGetter: callback function that defines custom CSV field mapping
Example usage:
type UserFilter struct {
OrganizationID uint
BranchID uint
}
presetConditions := &UserFilter{
OrganizationID: user.OrganizationID,
BranchID: *user.BranchID,
}
csvData, err := handler.GormNoPaginationCSVCustomWithPreset(db, presetConditions, filterRoot, func(user *User) map[string]any {
return map[string]any{
"Employee ID": user.ID,
"Full Name": fmt.Sprintf("%s %s", user.FirstName, user.LastName),
"Department": user.Department.Name,
}
})
func (*Handler[T]) GormNoPaginationCSVWithPreset ¶ added in v1.2.1
func (f *Handler[T]) GormNoPaginationCSVWithPreset( db *gorm.DB, presetConditions any, filterRoot Root, ) ([]byte, error)
GormNoPaginationCSVWithPreset is a convenience method that combines ApplyPresetConditions and GormNoPaginationCSV. It accepts preset conditions as a struct and applies them before filtering, returning results as CSV without pagination.
Example usage:
type AccountTag struct {
OrganizationID uint `gorm:"column:organization_id"`
BranchID uint `gorm:"column:branch_id"`
}
tag := &AccountTag{
OrganizationID: user.OrganizationID,
BranchID: *user.BranchID,
}
csvData, err := handler.GormNoPaginationCSVWithPreset(db, tag, filterRoot)
func (*Handler[T]) Hybrid ¶
func (f *Handler[T]) Hybrid( db *gorm.DB, threshold int, filterRoot Root, pageIndex int, pageSize int, ) (*PaginationResult[T], error)
Hybrid intelligently chooses between in-memory (DataQuery) and database (DataGorm) filtering based on estimated table size.
IMPORTANT: Respects pre-existing WHERE conditions on the db parameter. - If DataQuery is chosen (small dataset): fetches data using existing conditions, then filters in-memory - If DataGorm is chosen (large dataset): combines existing conditions with filterRoot filters in SQL
Example with pre-existing conditions:
db := gormDB.Where("organization_id = ? AND branch_id = ?", orgID, branchID)
result, err := handler.Hybrid(db, 10000, filterRoot, pageIndex, pageSize)
// DataQuery path: SELECT * FROM table WHERE organization_id = ? AND branch_id = ? (fetch all, filter in-memory)
// DataGorm path: SELECT * FROM table WHERE organization_id = ? AND branch_id = ? AND [filterRoot conditions]
func (*Handler[T]) HybridCSV ¶ added in v1.2.1
HybridCSV intelligently chooses between in-memory (DataQueryNoPageCSV) and database (GormNoPaginationCSV) filtering based on estimated table size, returning results as CSV bytes.
IMPORTANT: Respects pre-existing WHERE conditions on the db parameter. - If DataQueryNoPageCSV is chosen (small dataset): fetches data using existing conditions, then filters in-memory and exports to CSV - If GormNoPaginationCSV is chosen (large dataset): combines existing conditions with filterRoot filters in SQL and exports to CSV
Example with pre-existing conditions:
db := gormDB.Where("organization_id = ? AND branch_id = ?", orgID, branchID)
csvData, err := handler.HybridCSV(db, 10000, filterRoot)
// DataQueryNoPageCSV path: SELECT * FROM table WHERE organization_id = ? AND branch_id = ? (fetch all, filter in-memory, export CSV)
// GormNoPaginationCSV path: SELECT * FROM table WHERE organization_id = ? AND branch_id = ? AND [filterRoot conditions] (export CSV)
func (*Handler[T]) HybridCSVCustom ¶ added in v1.2.2
func (f *Handler[T]) HybridCSVCustom( db *gorm.DB, threshold int, filterRoot Root, customGetter func(*T) map[string]any, ) ([]byte, error)
HybridCSVCustom intelligently chooses between in-memory (DataQueryNoPageCSVCustom) and database (GormNoPaginationCSVCustom) approaches for CSV export based on estimated table size, using a custom callback function for field mapping. For small tables (below threshold), it uses in-memory filtering with full dataset retrieval. For large tables (above threshold), it uses database-level filtering to minimize memory usage.
Parameters:
- db: GORM database instance with any preset conditions
- threshold: row count threshold for switching between in-memory and database strategies
- filterRoot: filter configuration defining conditions, logic, and sorting
- customGetter: callback function that defines custom CSV field mapping
Strategy Selection:
- If estimated table rows <= threshold: DataQueryNoPageCSVCustom (in-memory processing)
- If estimated table rows > threshold: GormNoPaginationCSVCustom (database processing)
- If estimation fails: Falls back to GormNoPaginationCSVCustom (database processing)
Example usage:
csvData, err := handler.HybridCSVCustom(db, 10000, filterRoot, func(user *User) map[string]any {
return map[string]any{
"Employee Name": fmt.Sprintf("%s %s", user.FirstName, user.LastName),
"Contact Email": user.Email,
"Department": user.Department.Name,
"Join Date": user.CreatedAt.Format("2006-01-02"),
}
})
func (*Handler[T]) HybridCSVCustomWithPreset ¶ added in v1.2.2
func (f *Handler[T]) HybridCSVCustomWithPreset( db *gorm.DB, presetConditions any, threshold int, filterRoot Root, customGetter func(*T) map[string]any, ) ([]byte, error)
HybridCSVCustomWithPreset is a convenience method that combines preset conditions with HybridCSVCustom. It applies preset conditions to the database query before intelligent strategy selection and CSV export.
Parameters:
- db: GORM database instance
- presetConditions: struct or map with preset WHERE conditions to apply before filtering
- threshold: row count threshold for strategy selection
- filterRoot: filter configuration defining conditions, logic, and sorting
- customGetter: callback function that defines custom CSV field mapping
Example usage:
type OrganizationFilter struct {
OrganizationID uint
}
presetConditions := &OrganizationFilter{OrganizationID: user.OrganizationID}
csvData, err := handler.HybridCSVCustomWithPreset(db, presetConditions, 10000, filterRoot, func(user *User) map[string]any {
return map[string]any{
"ID": user.ID,
"Name": user.Name,
"Email": user.Email,
}
})
func (*Handler[T]) HybridCSVWithPreset ¶ added in v1.2.1
func (f *Handler[T]) HybridCSVWithPreset( db *gorm.DB, presetConditions any, threshold int, filterRoot Root, ) ([]byte, error)
HybridCSVWithPreset is a convenience method that combines preset conditions with HybridCSV. It accepts preset conditions as a struct and applies them before filtering, returning CSV results using hybrid strategy.
Example usage:
type AccountTag struct {
OrganizationID uint `gorm:"column:organization_id"`
BranchID uint `gorm:"column:branch_id"`
}
tag := &AccountTag{
OrganizationID: user.OrganizationID,
BranchID: *user.BranchID,
}
csvData, err := handler.HybridCSVWithPreset(db, tag, 10000, filterRoot)
type Mode ¶
type Mode string
Mode defines the type of comparison operation to perform
const ( ModeEqual Mode = "equal" // Exact match ModeNotEqual Mode = "notEqual" // Not equal ModeContains Mode = "contains" // Contains substring ModeNotContains Mode = "notContains" // Does not contain substring ModeStartsWith Mode = "startsWith" // Starts with prefix ModeEndsWith Mode = "endsWith" // Ends with suffix ModeIsEmpty Mode = "isEmpty" // Is empty or null ModeIsNotEmpty Mode = "isNotEmpty" // Is not empty ModeGT Mode = "gt" // Greater than ModeGTE Mode = "gte" // Greater than or equal ModeLT Mode = "lt" // Less than ModeLTE Mode = "lte" // Less than or equal ModeRange Mode = "range" // Between two values ModeBefore Mode = "before" // Before (date/time) ModeAfter Mode = "after" // After (date/time) )
mode constants define available comparison operations
type PaginationResult ¶
type PaginationResult[T any] struct { Data []*T `json:"data"` // Current page data TotalSize int `json:"totalSize"` // Total matching records TotalPage int `json:"totalPage"` // Total number of pages PageIndex int `json:"pageIndex"` // Current page index (0-based) PageSize int `json:"pageSize"` // Records per page }
PaginationResult contains filtered and paginated results
type RangeNumber ¶
type RangeNumber struct {
From float64 // Start of numeric range
To float64 // End of numeric range
}
RangeNumber represents a numeric range
type Root ¶
type Root struct {
FieldFilters []FieldFilter `json:"filters"` // List of filter conditions
SortFields []SortField `json:"sortFields"` // List of sort fields
Logic Logic `json:"logic"` // How to combine filters (AND/OR)
Preload []string `json:"preload"` // List of related entities to preload (only applicable for GORM)
}
Root represents the root filter configuration