deepgorm

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jan 10, 2024 License: MIT Imports: 8 Imported by: 0

README

🌌 Gorm Deep Filtering Plugin

Go package GitHub GitHub go.mod Go version

Ever wanted to filter objects on a deep level using only maps? This plugin allows you to do just that.

There's also an experimental feature that turns wildcard queries (*) into LIKE queries, but this may be changed in the future.

package main

func main () {
	filters := map[string]any{
		"name": "abc",
		"related_object": map[string]any{
			"title": "engineer",
		},
	}
}

Is automatically turned into a query that looks like this:

SELECT * FROM employees WHERE related_object_id IN (SELECT id FROM occupations WHERE title = "engineer")
  • gormlike turns WHERE-calls into LIkE queries if certain tokens were found
  • gormqonvert turns WHERE-calls into different queries if certain tokens were found
  • gormcase adds case insensitivity to WHERE queries
  • gormtestutil provides easy utility methods for unit-testing with gorm

⬇️ Installation

go get github.com/survivorbat/gorm-deep-filtering

📋 Usage

package main

import (
    "github.com/survivorbat/gorm-deep-filtering"
)

func main() {
	db, _ := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
	
	// Adds deep filtering
	db.Use(deepgorm.New())
	
	// Turns strings with wildcards (*) into LIKE queries (EXPERIMENTAL FEATURE)
	db.Use(deepgorm.New(deepgorm.Wildcards()))
}

🔭 Plans

Better error handling, logging.

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func AddDeepFilters

func AddDeepFilters(db *gorm.DB, objectType any, filters ...map[string]any) (*gorm.DB, error)

AddDeepFilters / addDeepFilter godoc

Gorm supports the following filtering:

type Person struct {
	Name string
}

map[string]any{
	"name": "Jake"
}

Which will return a list of people that are named 'Jake'. This is great for simple filtering but for more nested versions like the following it becomes problematic.

type Group struct {
	IDs int
	Name string
}

type Person struct {
	Name string
	Group Group
	GroupRef int
}

// Get all the users belonging to 'some group'

map[string]any{
	"group": map[string]any{
		"name": "some group",
	},
}

Gorm does not understand that we expected to filter users based on their group, it's not capable of doing that automatically. For this we need to use subqueries. Find more info here: https://gorm.io/docs/advanced_query.html

This function is constructed to automatically convert those nested maps ("group": map[string]...) into subqueries. In order to do this, it takes the following steps:

  1. Get all the struct-type fields from the incoming 'object', ignore all simple types and interfaces
  2. Loop through all the key/values in the incoming map
  3. Add all the simple types to a simpleMap, GORM can handle these, For all the special (nested) structs, add a subquery that uses WHERE on the subquery.
  4. Add the simple filters to the query and return it.
Example

Get all ObjectAs that are connected to ObhectB with Id 50

type ObjectB struct {
	ID int
}

type ObjectA struct {
	ID int

	ObjectB   *ObjectB `gorm:"foreignKey:ObjectBID"`
	ObjectBID int
}

db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
_ = db.Use(New())

db.Create(&ObjectA{
	ID: 1,
	ObjectB: &ObjectB{
		ID: 50,
	},
})

filters := map[string]any{
	"object_b": map[string]any{
		"id": 50,
	},
}

var result ObjectA
db.Where(filters).Find(&result)
fmt.Println(result)
Output:

func New

func New(opts ...Option) *deepGorm

New creates a new instance of the plugin that can be registered in gorm. Options allow you to enable specific features.

Example
db, _ := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})

_ = db.Use(New())
_ = db.Use(New(Wildcards()))
Output:

func Wildcards

func Wildcards() func(*deepGorm)

Wildcards enables wildcard use for LIKE queries in input filters, converting *'s to %'s for LIKE queries. NOTICE: This feature is experimental and might be changed in the future (different symbol for example).

Types

type Option

type Option func(*deepGorm)

Option is used to enable features in the New function

Jump to

Keyboard shortcuts

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