Skip to content

Commit

Permalink
Abstracting search
Browse files Browse the repository at this point in the history
  • Loading branch information
michael-brennan2005 committed May 22, 2024
1 parent a99c4f1 commit 23a293f
Show file tree
Hide file tree
Showing 15 changed files with 316 additions and 359 deletions.
6 changes: 3 additions & 3 deletions backend/entities/clubs/base/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func CreateClub(db *gorm.DB, userId uuid.UUID, club models.Club) (*models.Club,
return nil, err
}

err = search.UpsertClubToIndex(db, club.ID.String())
err = search.Upsert[models.Club](db, "clubs", club.ID.String(), &club)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -106,7 +106,7 @@ func UpdateClub(db *gorm.DB, id uuid.UUID, club models.Club) (*models.Club, erro
return nil, err
}

err = search.UpsertClubToIndex(db, club.ID.String())
err = search.Upsert[models.Club](db, "clubs", club.ID.String(), &club)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -140,7 +140,7 @@ func DeleteClub(db *gorm.DB, id uuid.UUID) error {
return result.Error
}

err = search.DeleteClubFromIndex(db, id.String())
err = search.Delete(db, "clubs", id.String())
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions backend/entities/events/base/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func CreateEvent(db *gorm.DB, event models.Event) (*models.Event, error) {
return nil, err
}

err := search.UpsertEventToIndex(db, event.ID.String())
err := search.Upsert[models.Event](db, "events", event.ID.String(), &event)
if err != nil {
return nil, err
}
Expand All @@ -55,9 +55,9 @@ func updateEvent(db *gorm.DB, id uuid.UUID, event models.Event) ([]models.Event,
return nil, result.Error
}

err := search.UpsertEventToIndex(db, id.String())
err := search.Upsert[models.Event](db, "events", id.String(), &event)
if err != nil {
return []models.Event{resultingEvent}, err
return nil, err
}

return []models.Event{resultingEvent}, nil
Expand Down Expand Up @@ -93,7 +93,7 @@ func DeleteEvent(db *gorm.DB, id uuid.UUID) error {
return result.Error
}

err := search.DeleteEventFromIndex(db, id.String())
err := search.Delete(db, "events", id.String())
if err != nil {
return err
}
Expand Down
23 changes: 23 additions & 0 deletions backend/entities/models/club.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,26 @@ type Club struct {
Event []Event `gorm:"many2many:club_events;" json:"-"`
Notifcation []Notification `gorm:"polymorphic:Reference;" json:"-"`
}

type ClubSearchDocument struct {
Name string `json:"name"`
Preview string `json:"preview"`
Description string `json:"description"`
NumMembers int `json:"num_members"`
Tags []string `json:"tags"`
}

func (c *Club) ToSearchDocument() interface{} {
tagIds := make([]string, len(c.Tag))
for i, tag := range c.Tag {
tagIds[i] = tag.ID.String()
}

return ClubSearchDocument{
Name: c.Name,
Preview: c.Preview,
Description: c.Description,
NumMembers: c.NumMembers,
Tags: tagIds,
}
}
35 changes: 35 additions & 0 deletions backend/entities/models/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,38 @@ type Event struct {
Tag []Tag `gorm:"many2many:event_tags;" json:"-"`
Notification []Notification `gorm:"polymorphic:Reference;" json:"-"`
}

// How Events are represented in the OpenSearch index.
type EventSearchDocument struct {
Name string `json:"name"`
Preview string `json:"preview"`
Description string `json:"description"`
EventType EventType `json:"event_type"`
StartTime time.Time `json:"start_time"`
EndTime time.Time `json:"end_time"`
Clubs []string `json:"clubs"`
Tags []string `json:"tags"`
}

func (c *Event) ToSearchDocument() interface{} {
tagIds := make([]string, len(c.Tag))
for i, tag := range c.Tag {
tagIds[i] = tag.ID.String()
}

clubIds := make([]string, len(c.Clubs))
for i, club := range c.Clubs {
clubIds[i] = club.ID.String()
}

return EventSearchDocument{
Name: c.Name,
Preview: c.Preview,
Description: c.Description,
EventType: c.EventType,
StartTime: c.StartTime,
EndTime: c.EndTime,
Tags: tagIds,
Clubs: clubIds,
}
}
6 changes: 3 additions & 3 deletions backend/search/base/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package base
import (
"net/http"

"github.com/GenerateNU/sac/backend/search"
search_types "github.com/GenerateNU/sac/backend/search/types"
"github.com/GenerateNU/sac/backend/utilities"
"github.com/gofiber/fiber/v2"
)
Expand All @@ -30,7 +30,7 @@ func NewSearchController(searchService SearchServiceInterface) *SearchController
// @Failure 500 {object} error
// @Router /search/clubs [get]
func (s *SearchController) SearchClubs(c *fiber.Ctx) error {
var searchQuery search.ClubSearchRequest
var searchQuery search_types.ClubSearchRequest

if err := c.BodyParser(&searchQuery); err != nil {
return utilities.InvalidJSON()
Expand Down Expand Up @@ -59,7 +59,7 @@ func (s *SearchController) SearchClubs(c *fiber.Ctx) error {
// @Failure 500 {object} error
// @Router /search/events [get]
func (s *SearchController) SearchEvents(c *fiber.Ctx) error {
var searchQuery search.EventSearchRequest
var searchQuery search_types.EventSearchRequest

if err := c.BodyParser(&searchQuery); err != nil {
return utilities.InvalidJSON()
Expand Down
2 changes: 1 addition & 1 deletion backend/search/base/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"github.com/GenerateNU/sac/backend/types"
)

func Search(params types.RouteParams) {
func SearchRoutes(params types.RouteParams) {
searchService := NewSearchService(params.ServiceParams)
searchController := NewSearchController(searchService)

Expand Down
15 changes: 8 additions & 7 deletions backend/search/base/service.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package base

import (
"github.com/GenerateNU/sac/backend/search"
"github.com/GenerateNU/sac/backend/entities/models"
search_types "github.com/GenerateNU/sac/backend/search/types"

"github.com/GenerateNU/sac/backend/types"
)

type SearchServiceInterface interface {
SearchClubs(query search.ClubSearchRequest) (*search.ClubSearchResult, error)
SearchEvents(query search.EventSearchRequest) (*search.EventSearchResult, error)
SearchClubs(query search_types.ClubSearchRequest) (*search_types.SearchResult[models.Club], error)
SearchEvents(query search_types.EventSearchRequest) (*search_types.SearchResult[models.Event], error)
}

type SearchService struct {
Expand All @@ -19,10 +20,10 @@ func NewSearchService(serviceParams types.ServiceParams) SearchServiceInterface
return &SearchService{serviceParams}
}

func (s *SearchService) SearchClubs(query search.ClubSearchRequest) (*search.ClubSearchResult, error) {
return SearchClubs(s.DB, query)
func (s *SearchService) SearchClubs(query search_types.ClubSearchRequest) (*search_types.SearchResult[models.Club], error) {
return Search[models.Club](s.DB, &query)
}

func (s *SearchService) SearchEvents(query search.EventSearchRequest) (*search.EventSearchResult, error) {
return SearchEvents(s.DB, query)
func (s *SearchService) SearchEvents(query search_types.EventSearchRequest) (*search_types.SearchResult[models.Event], error) {
return Search[models.Event](s.DB, &query)
}
115 changes: 15 additions & 100 deletions backend/search/base/transactions.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import (
"net/http"

"github.com/GenerateNU/sac/backend/constants"
"github.com/GenerateNU/sac/backend/entities/models"
"github.com/GenerateNU/sac/backend/search"
"github.com/GenerateNU/sac/backend/search/types"
"gorm.io/gorm"
)

Expand Down Expand Up @@ -47,8 +46,8 @@ func doSearchGetRequest[T, V any](url string, requestBody T) (*V, error) {
return &responseData, nil
}

func SearchClubs(db *gorm.DB, query search.ClubSearchRequest) (*search.ClubSearchResult, error) {
result, err := doSearchGetRequest[search.SearchEndpointRequest, search.SearchEndpointResponse]("/clubs/_search", query.ToSearchEndpointRequest())
func Search[T types.Searchable](db *gorm.DB, query types.SearchRequest) (*types.SearchResult[T], error) {
result, err := doSearchGetRequest[types.SearchEndpointRequest, types.SearchEndpointResponse](fmt.Sprintf("%s/_search", query.Index()), query.ToSearchEndpointRequest())
if err != nil {
return nil, nil
}
Expand All @@ -58,110 +57,26 @@ func SearchClubs(db *gorm.DB, query search.ClubSearchRequest) (*search.ClubSearc
ids[i] = result.Id
}

var clubs []models.Club
var results []T

if err = db.Model(&models.Club{}).Preload("Tag").Where("id IN ?", ids).Find(&clubs).Error; err != nil {
if err = db.Model(query.Model()).Preload("Tag").Preload("Clubs").Where("id IN ?", ids).Find(&results).Error; err != nil {
return nil, nil
}

return &search.ClubSearchResult{
Results: clubs,
return &types.SearchResult[T]{
Results: results,
}, nil
}

func SearchEvents(db *gorm.DB, query search.EventSearchRequest) (*search.EventSearchResult, error) {
result, err := doSearchGetRequest[search.SearchEndpointRequest, search.SearchEndpointResponse]("/events/_search", query.ToSearchEndpointRequest())
if err != nil {
return nil, nil
}

ids := make([]string, len(result.Hits.Hits))
for i, result := range result.Hits.Hits {
ids[i] = result.Id
}

var events []models.Event

if err = db.Model(&models.Event{}).Preload("Tag").Where("id IN ?", ids).Find(&events).Error; err != nil {
return nil, nil
}

return &search.EventSearchResult{
Results: events,
}, nil
}

func UpsertClubToIndex(db *gorm.DB, clubUuid string) error {
var club models.Club

if err := db.Preload("Tag").Where("id = ?", clubUuid).Find(&club).Error; err != nil {
return err
}

doc := search.ClubSearchDocumentFromClub(&club)
requestBody := search.Json{
"doc": doc,
"doc_as_upsert": true,
}
payload, err := json.Marshal(requestBody)

print(string(payload))
if err != nil {
return err
}

req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s/_update/%s", constants.SEARCH_URL, "clubs", club.ID), bytes.NewBuffer(payload))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

responseBody, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
print(string(responseBody))

return nil
}

func DeleteClubFromIndex(db *gorm.DB, clubUuid string) error {
req, err := http.NewRequest("DELETE", fmt.Sprintf("%s/%s/_doc/%s", constants.SEARCH_URL, "clubs", clubUuid), nil)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")

resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

responseBody, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
print(string(responseBody))

return nil
}

func UpsertEventToIndex(db *gorm.DB, eventUuid string) error {
var event models.Event
func Upsert[T types.Searchable](db *gorm.DB, index string, uuid string, model types.ToSearchDocument) error {
var elem T

if err := db.Preload("Clubs").Preload("Tag").Where("id = ?", eventUuid).Find(&event).Error; err != nil {
if err := db.Model(&model).Preload("Tag").Where("Clubs").Where("id = ?", uuid).Find(&elem).Error; err != nil {
return err
}

doc := search.EventSearchDocumentFromEvent(&event)
requestBody := search.Json{
doc := model.ToSearchDocument()
requestBody := types.Json{
"doc": doc,
"doc_as_upsert": true,
}
Expand All @@ -172,7 +87,7 @@ func UpsertEventToIndex(db *gorm.DB, eventUuid string) error {
return err
}

req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s/_update/%s", constants.SEARCH_URL, "events", event.ID), bytes.NewBuffer(payload))
req, err := http.NewRequest("POST", fmt.Sprintf("%s/%s/_update/%s", constants.SEARCH_URL, index, uuid), bytes.NewBuffer(payload))
if err != nil {
return err
}
Expand All @@ -193,8 +108,8 @@ func UpsertEventToIndex(db *gorm.DB, eventUuid string) error {
return nil
}

func DeleteEventFromIndex(db *gorm.DB, eventUuid string) error {
req, err := http.NewRequest("DELETE", fmt.Sprintf("%s/%s/_doc/%s", constants.SEARCH_URL, "events", eventUuid), nil)
func Delete(db *gorm.DB, index string, uuid string) error {
req, err := http.NewRequest("DELETE", fmt.Sprintf("%s/%s/_doc/%s", constants.SEARCH_URL, index, uuid), nil)
if err != nil {
return err
}
Expand Down
9 changes: 5 additions & 4 deletions backend/search/seed.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/GenerateNU/sac/backend/constants"
"github.com/GenerateNU/sac/backend/entities/models"
search_types "github.com/GenerateNU/sac/backend/search/types"
"github.com/GenerateNU/sac/backend/transactions"
"gorm.io/gorm"
)
Expand All @@ -35,15 +36,15 @@ func SeedClubs(db *gorm.DB) error {
var requestBodyBuilder strings.Builder

for _, club := range clubs {
indexData := BulkRequestCreate{}
indexData := search_types.BulkRequestCreate{}
indexData.Create.Index = "clubs"
indexData.Create.Id = club.ID.String()
indexJson, err := json.Marshal(indexData)
if err != nil {
return err
}

clubData := ClubSearchDocumentFromClub(&club)
clubData := club.ToSearchDocument()
clubJson, err := json.Marshal(clubData)
if err != nil {
return err
Expand Down Expand Up @@ -92,15 +93,15 @@ func SeedEvents(db *gorm.DB) error {
var requestBodyBuilder strings.Builder

for _, event := range events {
indexData := BulkRequestCreate{}
indexData := search_types.BulkRequestCreate{}
indexData.Create.Index = "events"
indexData.Create.Id = event.ID.String()
indexJson, err := json.Marshal(indexData)
if err != nil {
return err
}

eventData := EventSearchDocumentFromEvent(&event)
eventData := event.ToSearchDocument()
eventJson, err := json.Marshal(eventData)
if err != nil {
return err
Expand Down
Loading

0 comments on commit 23a293f

Please sign in to comment.