|
|
@ -14,13 +14,28 @@ import (
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
"github.com/urfave/cli/v2"
|
|
|
|
"net/http"
|
|
|
|
"net/http"
|
|
|
|
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
var (
|
|
|
|
resourcesIndex = "resources"
|
|
|
|
resourcesIndex = "resources"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
paginationPageHeader = "X-Pagination-Page"
|
|
|
|
|
|
|
|
paginationSizeHeader = "X-Pagination-Size"
|
|
|
|
|
|
|
|
paginationCountHeader = "X-Pagination-Count"
|
|
|
|
|
|
|
|
paginationPageQueryParam = "pagination-page"
|
|
|
|
|
|
|
|
paginationSizeQueryParam = "pagination-size"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defaultPaginationSize = 50
|
|
|
|
|
|
|
|
maxPaginationSize = 100
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type pagination struct {
|
|
|
|
|
|
|
|
page int
|
|
|
|
|
|
|
|
size int
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Represent a resource in elasticsearch
|
|
|
|
// Represent a resource in elasticsearch
|
|
|
|
type resourceIndex struct {
|
|
|
|
type resourceIndex struct {
|
|
|
|
URL string `json:"url"`
|
|
|
|
URL string `json:"url"`
|
|
|
@ -115,11 +130,26 @@ func searchResources(es *elastic.Client) echo.HandlerFunc {
|
|
|
|
return c.NoContent(http.StatusUnprocessableEntity)
|
|
|
|
return c.NoContent(http.StatusUnprocessableEntity)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Perform the search request.
|
|
|
|
// Acquire pagination
|
|
|
|
|
|
|
|
p := readPagination(c)
|
|
|
|
|
|
|
|
from := (p.page - 1) * p.size
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Build up search query
|
|
|
|
query := buildSearchQuery(string(b), c.QueryParam("keyword"))
|
|
|
|
query := buildSearchQuery(string(b), c.QueryParam("keyword"))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Get total count
|
|
|
|
|
|
|
|
totalCount, err := es.Count(resourcesIndex).Query(query).Do(context.Background())
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
log.Err(err).Msg("Error while counting on ES")
|
|
|
|
|
|
|
|
return c.NoContent(http.StatusInternalServerError)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Perform the search request.
|
|
|
|
res, err := es.Search().
|
|
|
|
res, err := es.Search().
|
|
|
|
Index(resourcesIndex).
|
|
|
|
Index(resourcesIndex).
|
|
|
|
Query(query).
|
|
|
|
Query(query).
|
|
|
|
|
|
|
|
From(from).
|
|
|
|
|
|
|
|
Size(p.size).
|
|
|
|
Do(context.Background())
|
|
|
|
Do(context.Background())
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
log.Err(err).Msg("Error while searching on ES")
|
|
|
|
log.Err(err).Msg("Error while searching on ES")
|
|
|
@ -142,6 +172,9 @@ func searchResources(es *elastic.Client) echo.HandlerFunc {
|
|
|
|
resources = append(resources, resource)
|
|
|
|
resources = append(resources, resource)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Write pagination
|
|
|
|
|
|
|
|
writePagination(c, p, totalCount)
|
|
|
|
|
|
|
|
|
|
|
|
return c.JSON(http.StatusOK, resources)
|
|
|
|
return c.JSON(http.StatusOK, resources)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -238,3 +271,29 @@ func setupElasticSearch(ctx context.Context, es *elastic.Client) error {
|
|
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func readPagination(c echo.Context) pagination {
|
|
|
|
|
|
|
|
paginationPage, err := strconv.Atoi(c.QueryParam(paginationPageQueryParam))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
paginationPage = 1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
paginationSize, err := strconv.Atoi(c.QueryParam(paginationSizeQueryParam))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
|
|
paginationSize = defaultPaginationSize
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prevent too much results from being returned
|
|
|
|
|
|
|
|
if paginationSize > maxPaginationSize {
|
|
|
|
|
|
|
|
paginationSize = maxPaginationSize
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return pagination{
|
|
|
|
|
|
|
|
page: paginationPage,
|
|
|
|
|
|
|
|
size: paginationSize,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func writePagination(c echo.Context, p pagination, totalCount int64) {
|
|
|
|
|
|
|
|
c.Response().Header().Set(paginationPageHeader, strconv.Itoa(p.page))
|
|
|
|
|
|
|
|
c.Response().Header().Set(paginationSizeHeader, strconv.Itoa(p.size))
|
|
|
|
|
|
|
|
c.Response().Header().Set(paginationCountHeader, strconv.FormatInt(totalCount, 10))
|
|
|
|
|
|
|
|
}
|
|
|
|