From 98a1e368342622998358d39f4916c12c7e266766 Mon Sep 17 00:00:00 2001 From: jamestang12 Date: Sun, 17 Jan 2021 18:16:33 -0500 Subject: [PATCH] Seach Created --- src/app/url_mappings.go | 1 + src/clients/elasticsearch/es_client.go | 15 ++++++++++++++ src/controllers/items_controller.go | 28 ++++++++++++++++++++++++++ src/domain/items/item_dao.go | 26 ++++++++++++++++++++++++ src/domain/queries/es_query_dao.go | 16 +++++++++++++++ src/domain/queries/es_query_dto.go | 10 +++++++++ src/services/items_service.go | 8 ++++++++ 7 files changed, 104 insertions(+) create mode 100644 src/domain/queries/es_query_dao.go create mode 100644 src/domain/queries/es_query_dto.go diff --git a/src/app/url_mappings.go b/src/app/url_mappings.go index c6654ff..8e93f2c 100644 --- a/src/app/url_mappings.go +++ b/src/app/url_mappings.go @@ -9,5 +9,6 @@ import ( func mapUrls() { router.HandleFunc("/items", controllers.ItemsController.Create).Methods(http.MethodPost) router.HandleFunc("/items/{id}", controllers.ItemsController.Get).Methods(http.MethodGet) + router.HandleFunc("/items/search", controllers.ItemsController.Search).Methods(http.MethodPost) } diff --git a/src/clients/elasticsearch/es_client.go b/src/clients/elasticsearch/es_client.go index bc9aa48..c9895bf 100644 --- a/src/clients/elasticsearch/es_client.go +++ b/src/clients/elasticsearch/es_client.go @@ -18,6 +18,7 @@ type esClientInterface interface { setClient(*elastic.Client) Index(string, string, interface{}) (*elastic.IndexResponse, error) Get(string, string, string) (*elastic.GetResult, error) + Search(string, elastic.Query) (*elastic.SearchResult, error) } type esClient struct { @@ -72,3 +73,17 @@ func (c *esClient) Get(index string, docType string, id string) (*elastic.GetRes } return result, nil } + +func (c *esClient) Search(index string, query elastic.Query) (*elastic.SearchResult, error) { + ctx := context.Background() + // if err := c.client.Search(index).Query(query).Validate(); err != nil { + // fmt.Println("result" + err.Error()) + // return nil, nil + // } + result, err := c.client.Search(index).Query(query).RestTotalHitsAsInt(true).Do(ctx) + if err != nil { + logger.Error(fmt.Sprintf("error when trying to search documents in index %s", index), err) + return nil, err + } + return result, nil +} diff --git a/src/controllers/items_controller.go b/src/controllers/items_controller.go index b552047..acc93e2 100644 --- a/src/controllers/items_controller.go +++ b/src/controllers/items_controller.go @@ -11,6 +11,7 @@ import ( "../../../bookstore_oauth_go/oauth" "../../../bookstore_utils_go/rest_errors" "../domain/items" + "../domain/queries" "../services" "../utils/http_utils" ) @@ -22,6 +23,7 @@ var ( type itemsControllerInterface interface { Create(http.ResponseWriter, *http.Request) Get(http.ResponseWriter, *http.Request) + Search(http.ResponseWriter, *http.Request) } type itemsController struct { @@ -90,3 +92,29 @@ func (c *itemsController) Get(w http.ResponseWriter, r *http.Request) { } http_utils.RespondJson(w, http.StatusOK, item) } + +func (c *itemsController) Search(w http.ResponseWriter, r *http.Request) { + byte, err := ioutil.ReadAll(r.Body) + if err != nil { + apiErr := rest_errors.NewBadRequestError("invalid json bocy") + http_utils.RespondError(w, apiErr) + return + } + + defer r.Body.Close() + + var query queries.EsQuery + if err := json.Unmarshal(byte, &query); err != nil { + apiErr := rest_errors.NewBadRequestError("invalid json bocy") + http_utils.RespondError(w, apiErr) + return + } + + items, searchErr := services.ItemsService.Search(query) + if searchErr != nil { + http_utils.RespondError(w, searchErr) + return + } + + http_utils.RespondJson(w, http.StatusOK, items) +} diff --git a/src/domain/items/item_dao.go b/src/domain/items/item_dao.go index 7cc95e6..8e37c2d 100644 --- a/src/domain/items/item_dao.go +++ b/src/domain/items/item_dao.go @@ -8,6 +8,7 @@ import ( "../../../../bookstore_utils_go/rest_errors" "../../clients/elasticsearch" + "../queries" ) const ( @@ -45,3 +46,28 @@ func (i *Item) Get() rest_errors.RestErr { i.Id = itemId return nil } + +func (i *Item) Search(query queries.EsQuery) ([]Item, rest_errors.RestErr) { + result, err := elasticsearch.Client.Search(indexItem, query.Build()) + if err != nil { + return nil, rest_errors.NewInternalServerError("error when trying to search documents", errors.New("database error")) + } + //fmt.Println(result) + + items := make([]Item, result.TotalHits()) + for index, hit := range result.Hits.Hits { + bytes, _ := hit.Source.MarshalJSON() + var item Item + if err := json.Unmarshal(bytes, &item); err != nil { + return nil, rest_errors.NewInternalServerError("error when trying to parse response", errors.New("database error")) + } + item.Id = hit.Id + items[index] = item + } + + if len(items) == 0 { + return nil, rest_errors.NewBadNotFoundError("no items found matching given criteria") + } + + return items, nil +} diff --git a/src/domain/queries/es_query_dao.go b/src/domain/queries/es_query_dao.go new file mode 100644 index 0000000..ad05899 --- /dev/null +++ b/src/domain/queries/es_query_dao.go @@ -0,0 +1,16 @@ +package queries + +import ( + "github.com/olivere/elastic" +) + +func (q EsQuery) Build() elastic.Query { + + query := elastic.NewBoolQuery() + equalsQueries := make([]elastic.Query, 0) + for _, eq := range q.Equals { + equalsQueries = append(equalsQueries, elastic.NewMatchQuery(eq.Field, eq.Value)) + } + query.Must(equalsQueries...) + return query +} diff --git a/src/domain/queries/es_query_dto.go b/src/domain/queries/es_query_dto.go new file mode 100644 index 0000000..056c306 --- /dev/null +++ b/src/domain/queries/es_query_dto.go @@ -0,0 +1,10 @@ +package queries + +type EsQuery struct { + Equals []FieldValue `json:"equals"` +} + +type FieldValue struct { + Field string `json:"field"` + Value interface{} `json:"value"` +} diff --git a/src/services/items_service.go b/src/services/items_service.go index f533b72..0c1b0da 100644 --- a/src/services/items_service.go +++ b/src/services/items_service.go @@ -3,6 +3,7 @@ package services import ( "../../../bookstore_utils_go/rest_errors" "../domain/items" + "../domain/queries" ) var ( @@ -12,6 +13,7 @@ var ( type itemsServiceInterface interface { Create(items.Item) (*items.Item, rest_errors.RestErr) Get(string) (*items.Item, rest_errors.RestErr) + Search(queries.EsQuery) ([]items.Item, rest_errors.RestErr) } type itemsService struct{} @@ -36,3 +38,9 @@ func (s *itemsService) Get(id string) (*items.Item, rest_errors.RestErr) { return &item, nil //return nil, rest_errors.NewRestErrpr("Not yet implement", http.StatusNotImplemented, "not_implemented", nil) } + +func (s *itemsService) Search(query queries.EsQuery) ([]items.Item, rest_errors.RestErr) { + dao := items.Item{} + return dao.Search(query) + +}