gormfilter

package
v0.9.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 29, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package gormfilter provides powerful and type-safe filtering capabilities for GORM queries.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClauseNot

func ClauseNot(exprs ...clause.Expression) clause.Expression

ClauseNot builds a NOT clause that correctly handles De Morgan's laws. This implementation applies negation to expressions with proper OR/AND conversion.

This is based on gorm.io/gorm/clause.Not but uses clause.OrWithSpace for proper negation. See: https://github.com/go-gorm/gorm/pull/7371

func Scope

func Scope(filter any, opts ...Option) func(db *gorm.DB) *gorm.DB

Scope returns a GORM scope function that applies the given filter to the query. The filter parameter should be a struct with fields matching the model's schema. Fields use filter types from the filter package (filter.String, filter.Int, etc.).

The filter struct can include:

  • Field filters using types from the filter package
  • Logical operators: And, Or, Not
  • Relationship filters (BelongsTo, HasOne)

Example:

type UserFilter struct {
    Name    *filter.String
    Age     *filter.Int
    Company *CompanyFilter  // BelongsTo relationship
    Profile *ProfileFilter  // HasOne relationship
    And     []*UserFilter
    Or      []*UserFilter
    Not     *UserFilter
}

// Simple filter
db.Scopes(gormfilter.Scope(&UserFilter{
    Name: &filter.String{Contains: lo.ToPtr("john"), Fold: true},
})).Find(&users)

// Complex filter with relationships
db.Scopes(gormfilter.Scope(&UserFilter{
    Age: &filter.Int{Gte: lo.ToPtr(18)},
    Company: &CompanyFilter{
        Name: &filter.String{Eq: lo.ToPtr("Tech Corp")},
    },
})).Find(&users)

// Logical combinations
db.Scopes(gormfilter.Scope(&UserFilter{
    Or: []*UserFilter{
        {Age: &filter.Int{Lt: lo.ToPtr(25)}},
        {Age: &filter.Int{Gt: lo.ToPtr(60)}},
    },
})).Find(&users)

Options:

  • WithDisableBelongsTo: Disables filtering by belongs_to relationships
  • WithDisableHasOne: Disables filtering by has_one relationships
  • WithDisableRelationships: Disables filtering by all relationship types

Types

type FieldColumnFunc added in v0.9.0

type FieldColumnFunc func(input *FieldColumnInput) (*FieldColumnOutput, error)

FieldColumnFunc builds a column for a given field.

type FieldColumnInput added in v0.9.0

type FieldColumnInput struct {
	FieldName string
	Fold      bool
}

FieldColumnInput provides context for building a field's column.

type FieldColumnOutput added in v0.9.0

type FieldColumnOutput struct {
	Column any // clause.Column or clause.Expr (for computed expressions like LOWER())
}

FieldColumnOutput specifies the column to use for filtering. Column can be clause.Column or clause.Expr (for computed expressions like LOWER()).

type NotConditions

type NotConditions struct {
	Exprs []clause.Expression
}

NotConditions represents a NOT clause with support for proper negation of complex expressions.

func (NotConditions) Build

func (not NotConditions) Build(builder clause.Builder)

type Option

type Option func(*options)

func WithDisableBelongsTo

func WithDisableBelongsTo() Option

WithDisableBelongsTo returns an option that disables filtering by belongs_to relationships. This can be useful when you want to prevent complex subqueries or restrict filtering to direct fields only.

func WithDisableHasOne added in v0.6.1

func WithDisableHasOne() Option

WithDisableHasOne returns an option that disables filtering by has_one relationships. This can be useful when you want to prevent complex subqueries or restrict filtering to direct fields only.

func WithDisableRelationships added in v0.6.1

func WithDisableRelationships() Option

WithDisableRelationships returns an option that disables filtering by all relationship types.

func WithFieldColumnHook added in v0.9.0

func WithFieldColumnHook(hooks ...func(next FieldColumnFunc) FieldColumnFunc) Option

WithFieldColumnHook installs a hook to customize how field columns are built. This allows dynamic column resolution based on field name and filter context (e.g., Fold). Multiple hooks can be chained together.

Example:

// Filter on JSON field: WHERE "snapshot"->>'name' = 'Old Name'
snapshotHook := func(next gormfilter.FieldColumnFunc) gormfilter.FieldColumnFunc {
    return func(input *gormfilter.FieldColumnInput) (*gormfilter.FieldColumnOutput, error) {
        if input.FieldName == "SnapshotName" {
            var column any = clause.Column{Name: `"snapshot"->>'name'`, Raw: true}
            if input.Fold {
                column = clause.Expr{SQL: "LOWER(?)", Vars: []any{column}}
            }
            return &gormfilter.FieldColumnOutput{Column: column}, nil
        }
        return next(input)
    }
}

db.Scopes(gormfilter.Scope(&ProductFilter{
    Name: &filter.String{Eq: lo.ToPtr("Old Name")},
}, gormfilter.WithFieldColumnHook(snapshotHook)))

type RelationshipInExpr added in v0.6.1

type RelationshipInExpr struct {
	clause.Expr
	LocalColumn clause.Column
}

RelationshipInExpr represents an IN subquery expression for relationship filters (BelongsTo, HasOne)

func (*RelationshipInExpr) Build added in v0.6.1

func (in *RelationshipInExpr) Build(builder clause.Builder)

func (*RelationshipInExpr) NegationBuild added in v0.6.1

func (in *RelationshipInExpr) NegationBuild(builder clause.Builder)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL