go-gorm / gorm.io

GORM official site

Home Page:https://gorm.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How can i use proload with scopes to query

victormazeli opened this issue · comments

https://gorm.io/docs/preload.html#Auto-Preloading

How can i use proload with scopes to query ?

i am trying to get gorm preload and scopes to work with find, i am trying to fetch all properties and preload all it images, but it does not work with what i have in my code, but if i do a query to query a single property (using FIRST ) i get the images preloaded. below is the code;

import (
	"database/sql"
	"encoding/json"
	"time"

	"gopkg.in/guregu/null.v4"
	_ "gopkg.in/guregu/null.v4"
)

type Property struct {
	ID                   uint            `json:"id" gorm:"primaryKey"`
	PropertyTitle        string          `json:"property_title" gorm:"type:varchar(255)"`
	Description          null.String     `json:"description" gorm:"type:text"`
	Floors               null.String     `json:"floors" gorm:"type:varchar(255)"`
	NumberOfRooms        null.String     `json:"number_of_rooms" gorm:"type:varchar(255)"`
	BedRooms             null.String     `json:"bed_rooms" gorm:"type:varchar(255)"`
	BathRooms            null.String     `json:"bath_rooms" gorm:"type:varchar(255)"`
	CloakRooms           null.String     `json:"cloak_rooms" gorm:"type:varchar(255)"`
	UtilityRooms         null.String     `json:"utility_rooms" gorm:"type:varchar(255)"`
	Conservatory         null.String     `json:"conservatory" gorm:"type:varchar(255)"`
	EntranceHall         null.String     `json:"entrance_hall" gorm:"type:varchar(255)"`
	FrontYard            null.String     `json:"front_yard" gorm:"type:varchar(255)"`
	MudRoom              null.String     `json:"mud_room" gorm:"type:varchar(255)"`
	FurnishedRoom        null.String     `json:"furnished_room" gorm:"type:varchar(255)"`
	Garden               null.String     `json:"garden" gorm:"type:varchar(255)"`
	Garage               null.String     `json:"garage" gorm:"type:varchar(255)"`
	Ensuite              null.String     `json:"ensuite" gorm:"type:varchar(255)"`
	CharacterFeature     null.String     `json:"character_feature" gorm:"type:text"`
	EpcRatings           null.String     `json:"epc_ratings" gorm:"type:varchar(255)"`
	PetsAllowed          null.String     `json:"pets_allowed" gorm:"type:varchar(255)"`
	SmokingAllowed       null.String     `json:"smoking_allowed" gorm:"type:varchar(255)"`
	DssAllowed           null.String     `json:"dss_allowed" gorm:"type:varchar(255)"`
	SharersAllowed       null.String     `json:"sharers_allowed" gorm:"type:varchar(255)"`
	AverageRating        null.Float      `json:"average_rating" gorm:"type:float"`
	Address              null.String     `json:"address" gorm:"type:text"`
	State                NullString      `json:"state" gorm:"type:text"`
	Latitude             float64         `json:"latitude"`
	Longitude            float64         `json:"longitude"`
	City                 string          `json:"city" gorm:"type:varchar(255)"`
	Country              string          `json:"country" gorm:"type:varchar(255)"`
	PostalCode           string          `json:"postal_code" gorm:"type:varchar(255)"`
	PropertyImages       []PropertyImage `json:"property_images"`
	PropertyType         string          `json:"property_type"`
	PropertyDetachedType string          `json:"property_detached_type"`
	UserID               uint            `json:"user_id"`
	IsVisible            int64           `json:"is_visible" gorm:"default:0"`
	CreatedAt            time.Time       `json:"created_at"`
	UpdatedAt            time.Time       `json:"updated_at"`
	DeletedAt            null.Time       `json:"deleted_at"`
}

type NullString struct {
	sql.NullString
}

// MarshalJSON for NullString
func (ns *NullString) MarshalJSON() ([]byte, error) {
	if !ns.Valid {
		return []byte("null"), nil
	}
	return json.Marshal(ns.String)
}

type PropertyImage struct {
	ID         uint      `json:"id" gorm:"primaryKey"`
	ImageUrl   string    `json:"image_url" gorm:"type:varchar(255)"`
	PropertyID uint      `json:"property_id" gorm:"foreignkey:PropertyID"`
	CreatedAt  time.Time `json:"created_at"`
	UpdatedAt  time.Time `json:"updated_at"`
	DeletedAt  null.Time `json:"deleted_at"`
}


package main

import (
	"math"
	"rateMyRentalBackend/http/response"
	"rateMyRentalBackend/models"
	"strconv"

	"gorm.io/gorm"
)

func Paginate(page int64, limit int64, query map[string]interface{}, sort string) func(db *gorm.DB) *gorm.DB {

	offset := (page - 1) * limit

	return func(db *gorm.DB) *gorm.DB {
		return db.Offset(int(offset)).Limit(int(limit)).Where(query).Order(sort)
	}
}

func Pagination(model interface{}, page string, limit string, sort string, query map[string]interface{}, preloadQuery *string, db *gorm.DB) (*response.PaginationDTO, error) {
	parsePage, er := strconv.ParseInt(page, 0, 64)
	if er != nil {
		return nil, er
	}

	// parse query "limit" to int
	parseLimit, e := strconv.ParseInt(limit, 0, 64)
	if e != nil {
		return nil, e
	}

	var totalRows int64

	// Explicitly set the table name for the model before using it in the query
	db.Model(&models.Property{}).Where(query).Count(&totalRows)

	totalPages := int(math.Ceil(float64(totalRows)) / float64(parseLimit))

	var data []map[string]interface{}
	queryDB := db.Model(&models.Property{}).Scopes(Paginate(parsePage, parseLimit, query, sort))

	if preloadQuery != nil {
		preloadAssociation := *preloadQuery
		queryDB = queryDB.Preload(preloadAssociation)
	}

	if result := queryDB.Find(&data).Error; result != nil {
		return nil, result
	}

	paginatedResult := &response.PaginationDTO{
		Docs:       data,
		TotalPages: int64(totalPages),
		TotalDocs:  totalRows,
		Page:       parsePage,
		Limit:      parseLimit,
	}

	return paginatedResult, nil
}