Skip to content

Commit

Permalink
feat(search): trying to merge search from API and HTML
Browse files Browse the repository at this point in the history
  • Loading branch information
rande committed Nov 10, 2023
1 parent a410a88 commit 94ea9ef
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 105 deletions.
18 changes: 9 additions & 9 deletions modules/search/search_basic_index.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,23 @@ type Index struct {
Page int64 `json:"page"`
PerPage int64 `json:"per_page"`
OrderBy []*Param `json:"order_by"`
Uuid *Param `json:"uuid"`
Type *Param `json:"type"`
Uuid []*Param `json:"uuid"`
Type []*Param `json:"type"`
Name *Param `json:"name"`
Slug *Param `json:"slug"`
Data []*Param `json:"data"`
Meta []*Param `json:"meta"`
Status *Param `json:"status"`
Weight *Param `json:"weight"`
Status []*Param `json:"status"`
Weight []*Param `json:"weight"`
Revision *Param `json:"revision"`
Enabled *Param `json:"enabled"`
Deleted *Param `json:"deleted"`
Current *Param `json:"current"`
UpdatedBy *Param `json:"updated_by"`
CreatedBy *Param `json:"created_by"`
ParentUuid *Param `json:"parent_uuid"`
SetUuid *Param `json:"set_uuid"`
Source *Param `json:"source"`
UpdatedBy []*Param `json:"updated_by"`
CreatedBy []*Param `json:"created_by"`
ParentUuid []*Param `json:"parent_uuid"`
SetUuid []*Param `json:"set_uuid"`
Source []*Param `json:"source"`
}

type IndexHandler struct {
Expand Down
99 changes: 45 additions & 54 deletions modules/search/search_driver_pgsql.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package search

import (
"fmt"
"net/url"
"strings"

sq "github.com/Masterminds/squirrel"
Expand Down Expand Up @@ -56,81 +57,71 @@ type SearchPager struct {
PerPage uint64
Next uint64
Previous uint64
Form *SearchForm
}

type SearchPGSQL struct {
}

func (s *SearchPGSQL) BuildQuery(searchForm *SearchForm, query sq.SelectBuilder) sq.SelectBuilder {

for _, order := range searchForm.OrderBy {
helper.PanicIf(len(order.SubField) == 0, "OrderBy field name is empty")
func (s *SearchPager) PageQuery(page uint64) url.Values {
params := s.Form.UrlValues()

query = query.OrderBy(GetJsonQuery(order.SubField, "->") + " " + order.Operation)
}
params.Set("page", fmt.Sprintf("%v", page))

if searchForm.Uuid != nil {
query = query.Where(sq.Eq{"uuid": searchForm.Uuid.Value})
}

if searchForm.Type != nil {
query = query.Where(sq.Eq{"type": searchForm.Type.Value})
}
return params
}

if searchForm.Name != nil {
query = query.Where("name = ?", searchForm.Name.Value)
}
type SearchPGSQL struct {
}

if searchForm.Slug != nil {
query = query.Where("slug = ?", searchForm.Slug.Value)
func AddEqClause(column string, query sq.SelectBuilder, params []*Param) sq.SelectBuilder {
if len(params) == 0 {
return query
}

query = GetJsonSearchQuery(query, searchForm.Data, "data")
query = GetJsonSearchQuery(query, searchForm.Meta, "meta")

if searchForm.Status != nil {
query = query.Where(sq.Eq{"status": searchForm.Status.Value})
values := []interface{}{}
for _, param := range params {
values = append(values, param.Value)
}

if searchForm.Weight != nil {
query = query.Where("weight = ?", searchForm.Weight.Value)
}
query = query.Where(sq.Eq{column: values})

if searchForm.Revision != nil {
query = query.Where("revision = ?", searchForm.Revision.Value)
}
return query
}

if searchForm.Enabled != nil {
query = query.Where("enabled = ?", searchForm.Enabled.Value)
func AddClause(column string, query sq.SelectBuilder, params *Param) sq.SelectBuilder {
if params == nil {
return query
}

if searchForm.Deleted != nil {
query = query.Where("deleted = ?", searchForm.Deleted.Value)
}
query = query.Where(fmt.Sprintf("%s = ?", column), params.Value)

if searchForm.Current != nil {
query = query.Where("current = ?", searchForm.Current.Value)
}
return query
}

if searchForm.UpdatedBy != nil {
query = query.Where(sq.Eq{"updated_by": searchForm.UpdatedBy.Value})
}
func (s *SearchPGSQL) BuildQuery(searchForm *SearchForm, query sq.SelectBuilder) sq.SelectBuilder {
for _, order := range searchForm.OrderBy {
helper.PanicIf(len(order.SubField) == 0, "OrderBy field name is empty")

if searchForm.CreatedBy != nil {
query = query.Where(sq.Eq{"created_by": searchForm.CreatedBy.Value})
query = query.OrderBy(GetJsonQuery(order.SubField, "->") + " " + order.Operation)
}

if searchForm.ParentUuid != nil {
query = query.Where(sq.Eq{"parent_uuid": searchForm.ParentUuid.Value})
}
query = AddEqClause("uuid", query, searchForm.Uuid)
query = AddEqClause("type", query, searchForm.Type)
query = AddEqClause("updated_by", query, searchForm.UpdatedBy)
query = AddEqClause("created_by", query, searchForm.CreatedBy)
query = AddEqClause("parent_uuid", query, searchForm.ParentUuid)
query = AddEqClause("set_uuid", query, searchForm.SetUuid)
query = AddEqClause("source", query, searchForm.Source)
query = AddEqClause("status", query, searchForm.Status)
query = AddEqClause("weight", query, searchForm.Weight)

if searchForm.SetUuid != nil {
query = query.Where(sq.Eq{"set_uuid": searchForm.SetUuid.Value})
}
query = AddClause("name", query, searchForm.Name)
query = AddClause("slug", query, searchForm.Slug)
query = AddClause("revision", query, searchForm.Revision)
query = AddClause("enabled", query, searchForm.Enabled)
query = AddClause("deleted", query, searchForm.Deleted)
query = AddClause("current", query, searchForm.Current)

if searchForm.Source != nil {
query = query.Where(sq.Eq{"source": searchForm.Source.Value})
}
query = GetJsonSearchQuery(query, searchForm.Data, "data")
query = GetJsonSearchQuery(query, searchForm.Meta, "meta")

return query
}
99 changes: 81 additions & 18 deletions modules/search/search_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
package search

import (
"fmt"
"net/url"
"strconv"

sq "github.com/Masterminds/squirrel"
"github.com/rande/gonode/core/squirrel"
"github.com/rande/gonode/modules/base"
Expand Down Expand Up @@ -39,23 +43,81 @@ type SearchForm struct {
Page uint64 `json:"page"`
PerPage uint64 `json:"per_page"`
OrderBy []*Param `json:"order_by"`
Uuid *Param `json:"uuid"`
Type *Param `json:"type"`
Uuid []*Param `json:"uuid"`
Type []*Param `json:"type"`
Name *Param `json:"name"`
Slug *Param `json:"slug"`
Data []*Param `json:"data"`
Meta []*Param `json:"meta"`
Status *Param `json:"status"`
Weight *Param `json:"weight"`
Status []*Param `json:"status"`
Weight []*Param `json:"weight"`
Revision *Param `json:"revision"`
Enabled *Param `json:"enabled"`
Deleted *Param `json:"deleted"`
Current *Param `json:"current"`
UpdatedBy *Param `json:"updated_by"`
CreatedBy *Param `json:"created_by"`
ParentUuid *Param `json:"parent_uuid"`
SetUuid *Param `json:"set_uuid"`
Source *Param `json:"source"`
UpdatedBy []*Param `json:"updated_by"`
CreatedBy []*Param `json:"created_by"`
ParentUuid []*Param `json:"parent_uuid"`
SetUuid []*Param `json:"set_uuid"`
Source []*Param `json:"source"`
}

func addUrlValue(values url.Values, name string, param *Param) {
if param == nil || param.Value == nil {
return
}

values.Add(name, fmt.Sprintf("%v", param.Value))
}

func addUrlValues(values url.Values, name string, param []*Param) {
if param == nil {
return
}

for _, param := range param {
addUrlValue(values, name, param)
}
}

func (s *SearchForm) UrlValues() url.Values {
values := url.Values{}
values.Add("page", strconv.FormatUint(s.Page, 10))
values.Add("per_page", strconv.FormatUint(s.PerPage, 10))

addUrlValues(values, "uuid", s.Uuid)
addUrlValues(values, "type", s.Type)
addUrlValues(values, "status", s.Status)
addUrlValues(values, "weight", s.Weight)
addUrlValues(values, "updated_by", s.UpdatedBy)
addUrlValues(values, "order_by", s.OrderBy)
addUrlValues(values, "created_by", s.CreatedBy)
addUrlValues(values, "parent_uuid", s.ParentUuid)
addUrlValues(values, "set_uuid", s.SetUuid)
addUrlValues(values, "source", s.Source)

addUrlValue(values, "name", s.Name)
addUrlValue(values, "slug", s.Slug)
addUrlValue(values, "revision", s.Revision)
addUrlValue(values, "enabled", s.Enabled)
addUrlValue(values, "deleted", s.Deleted)
addUrlValue(values, "current", s.Current)

for _, param := range s.Meta {
if param.Value == nil {
continue
}
values.Add(fmt.Sprintf("meta.%s", param.SubField), fmt.Sprintf("%v", param.Value))
}

for _, param := range s.Data {
if param.Value == nil {
continue
}
values.Add(fmt.Sprintf("data.%s", param.SubField), fmt.Sprintf("%v", param.Value))
}

return values
}

func NewSearchForm() *SearchForm {
Expand Down Expand Up @@ -92,8 +154,8 @@ func NewSearchFormFromIndex(index *Index) *SearchForm {
return search
}

func GetPager(search *SearchForm, manager base.NodeManager, engine *SearchPGSQL, options *base.AccessOptions) *SearchPager {
query := engine.BuildQuery(search, manager.SelectBuilder(base.NewSelectOptions()))
func GetPager(form *SearchForm, manager base.NodeManager, engine *SearchPGSQL, options *base.AccessOptions) *SearchPager {
query := engine.BuildQuery(form, manager.SelectBuilder(base.NewSelectOptions()))

// apply security access
if options != nil && len(options.Roles) > 0 {
Expand All @@ -102,24 +164,25 @@ func GetPager(search *SearchForm, manager base.NodeManager, engine *SearchPGSQL,
query = query.Where(squirrel.NewExprSlice("\"access\" && ARRAY["+sq.Placeholders(len(options.Roles))+"]", value))
}

list := manager.FindBy(query, (search.Page-1)*search.PerPage, search.PerPage+1)
list := manager.FindBy(query, (form.Page-1)*form.PerPage, form.PerPage+1)

pager := &SearchPager{
Page: search.Page,
PerPage: search.PerPage,
Page: form.Page,
PerPage: form.PerPage,
Elements: make([]*base.Node, 0),
Previous: uint64(0),
Next: uint64(0),
Form: form,
}

if search.Page > 1 {
pager.Previous = search.Page - 1
if form.Page > 1 {
pager.Previous = form.Page - 1
}

counter := uint64(0)
for e := list.Front(); e != nil; e = e.Next() {
if counter == search.PerPage {
pager.Next = search.Page + 1
if counter == form.PerPage {
pager.Next = form.Page + 1
break
}
pager.Elements = append(pager.Elements, e.Value.(*base.Node))
Expand Down
22 changes: 22 additions & 0 deletions modules/search/search_form_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright © 2014-2023 Thomas Rabaix <thomas.rabaix@gmail.com>.
//
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.

package search

import (
"testing"

"github.com/stretchr/testify/assert"
)

func Test_SearchForm_UrlValues(t *testing.T) {
s := &SearchForm{
PerPage: 32,
Page: 1,
Type: []*Param{NewParam("blog.type")},
}

assert.Equal(t, s.UrlValues().Encode(), "page=1&per_page=32&type=blog.type")
}
Loading

0 comments on commit 94ea9ef

Please sign in to comment.