-
Notifications
You must be signed in to change notification settings - Fork 898
Return full item data instead of just ids option #1193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 8 commits
eed368c
643bb16
204e8ec
87cc1fa
50dd26d
3d6f362
3d2a5a7
48790d9
4f0718b
82d19c9
e87468c
40b0bea
ce0ebdd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -539,8 +539,9 @@ func (s *RestServer) CreateWebService() { | |
| Param(ws.QueryParameter("write-back-delay", "Timestamp delay of write back feedback (format 0h0m0s)").DataType("string")). | ||
| Param(ws.QueryParameter("n", "Number of returned items").DataType("integer")). | ||
| Param(ws.QueryParameter("offset", "Offset of returned items").DataType("integer")). | ||
| Returns(http.StatusOK, "OK", []string{}). | ||
| Writes([]string{})) | ||
| Param(ws.QueryParameter("include-items", "Include full item data in response").DataType("boolean")). | ||
| Returns(http.StatusOK, "OK", RecommendResponse{}). | ||
| Writes(RecommendResponse{})) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not change Writes |
||
| ws.Route(ws.GET("/recommend/{user-id}/{category}").To(s.getRecommend). | ||
| Deprecate().Doc("Get recommendation for user. Set X-API-Version: 2 to return scores."). | ||
| Metadata(restfulspec.KeyOpenAPITags, []string{RecommendationAPITag}). | ||
|
|
@@ -552,8 +553,9 @@ func (s *RestServer) CreateWebService() { | |
| Param(ws.QueryParameter("write-back-delay", "Timestamp delay of write back feedback (format 0h0m0s)").DataType("string")). | ||
| Param(ws.QueryParameter("n", "Number of returned items").DataType("integer")). | ||
| Param(ws.QueryParameter("offset", "Offset of returned items").DataType("integer")). | ||
| Returns(http.StatusOK, "OK", []string{}). | ||
| Writes([]string{})) | ||
| Param(ws.QueryParameter("include-items", "Include full item data in response").DataType("boolean")). | ||
|
AbhilashVijayakumar marked this conversation as resolved.
Outdated
|
||
| Returns(http.StatusOK, "OK", RecommendResponse{}). | ||
| Writes(RecommendResponse{})) | ||
| ws.Route(ws.POST("/session/recommend").To(s.sessionRecommend). | ||
| Doc("Get recommendation for session."). | ||
| Metadata(restfulspec.KeyOpenAPITags, []string{RecommendationAPITag}). | ||
|
|
@@ -883,13 +885,33 @@ func (s *RestServer) getRecommend(request *restful.Request, response *restful.Re | |
| } else { | ||
| scores = []cache.Score{} | ||
| } | ||
| results := lo.Map(scores, func(item cache.Score, index int) string { | ||
| itemIds := lo.Map(scores, func(item cache.Score, index int) string { | ||
| return item.Id | ||
| }) | ||
| includeItems := request.QueryParameter("include-items") == "true" | ||
| var items []data.Item | ||
| if includeItems { | ||
| // fetch full item data only when requested | ||
| fetchedItems, err := s.DataClient.BatchGetItems(ctx, itemIds) | ||
| if err != nil { | ||
| InternalServerError(response, err) | ||
| return | ||
| } | ||
| // order items to match itemIds order | ||
| itemMap := make(map[string]data.Item, len(fetchedItems)) | ||
| for _, item := range fetchedItems { | ||
| itemMap[item.ItemId] = item | ||
| } | ||
| for _, id := range itemIds { | ||
| if item, ok := itemMap[id]; ok { | ||
| items = append(items, item) | ||
| } | ||
| } | ||
| } | ||
| // write back | ||
| if writeBackFeedback != "" { | ||
| startTime := time.Now() | ||
| for _, itemId := range results { | ||
| for _, itemId := range itemIds { | ||
| // insert to data store | ||
| feedback := data.Feedback{ | ||
| FeedbackKey: data.FeedbackKey{ | ||
|
|
@@ -911,7 +933,15 @@ func (s *RestServer) getRecommend(request *restful.Request, response *restful.Re | |
| Ok(response, scores) | ||
|
AbhilashVijayakumar marked this conversation as resolved.
Outdated
|
||
| return | ||
| } | ||
| Ok(response, results) | ||
| // Send response: include full item data only when requested | ||
| if includeItems { | ||
| Ok(response, RecommendResponse{ | ||
| ItemIds: itemIds, | ||
| Items: items, | ||
| }) | ||
| } else { | ||
| Ok(response, itemIds) | ||
| } | ||
| } | ||
|
|
||
| func (s *RestServer) sessionRecommend(request *restful.Request, response *restful.Response) { | ||
|
|
@@ -1011,6 +1041,13 @@ func (s *RestServer) sessionRecommend(request *restful.Request, response *restfu | |
| Ok(response, result) | ||
| } | ||
|
|
||
| // RecommendResponse is the response for the recommend endpoint. | ||
| // It includes both item IDs (for backward compatibility) and full item data. | ||
| type RecommendResponse struct { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Return array and remove structure to be compatible with no items situation |
||
| ItemIds []string `json:"item_ids"` | ||
| Items []data.Item `json:"items"` | ||
| } | ||
|
|
||
| // Success is the returned data structure for data insert operations. | ||
| type Success struct { | ||
| RowAffected int | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,6 +88,25 @@ | |
| return string(s) | ||
| } | ||
|
|
||
| // marshalRecommend builds the expected JSON for the recommend endpoint. | ||
| // It fetches full item data from the test DataClient and orders them to match itemIds. | ||
| func (suite *ServerTestSuite) marshalRecommend(itemIds []string) string { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rename to marshal scored items |
||
| ctx := context.Background() | ||
|
Check failure on line 94 in server/rest_test.go
|
||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use suite.T(). Context() |
||
| fetched, err := suite.DataClient.BatchGetItems(ctx, itemIds) | ||
| suite.NoError(err) | ||
| itemMap := make(map[string]data.Item, len(fetched)) | ||
| for _, item := range fetched { | ||
| itemMap[item.ItemId] = item | ||
| } | ||
| var items []data.Item | ||
| for _, id := range itemIds { | ||
| if item, ok := itemMap[id]; ok { | ||
| items = append(items, item) | ||
| } | ||
| } | ||
| return suite.marshal(RecommendResponse{ItemIds: itemIds, Items: items}) | ||
| } | ||
|
|
||
| func (suite *ServerTestSuite) TestUsers() { | ||
| t := suite.T() | ||
| users := []data.User{ | ||
|
|
@@ -1083,6 +1102,19 @@ | |
| Status(http.StatusOK). | ||
| Body(suite.marshal([]string{"6", "7", "8"})). | ||
| End() | ||
| // Test include-items=true returns full item data | ||
| apitest.New(). | ||
| Handler(suite.handler). | ||
| Get("/api/recommend/0"). | ||
| Header("X-API-Key", apiKey). | ||
| QueryParams(map[string]string{ | ||
| "n": "3", | ||
| "include-items": "true", | ||
| }). | ||
| Expect(suite.T()). | ||
| Status(http.StatusOK). | ||
| Body(suite.marshalRecommend([]string{"6", "7", "8"})). | ||
| End() | ||
| } | ||
|
|
||
| func (suite *ServerTestSuite) TestGetRecommendsMultiCategories() { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.