deepgorm

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jan 29, 2024 License: MIT Imports: 7 Imported by: 1

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.

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())
}

🔭 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() gorm.Plugin

New creates a new instance of the plugin that can be registered in gorm.

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

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

Types

This section is empty.

Jump to

Keyboard shortcuts

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