Skip to content
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

add SearchRaw to return raw JSON from search #377

Merged
merged 2 commits into from Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions index.go
@@ -1,6 +1,7 @@
package meilisearch

import (
"encoding/json"
"net/http"
"strconv"
"strings"
Expand Down Expand Up @@ -38,6 +39,7 @@ type IndexInterface interface {
DeleteDocuments(uid []string) (resp *TaskInfo, err error)
DeleteAllDocuments() (resp *TaskInfo, err error)
Search(query string, request *SearchRequest) (*SearchResponse, error)
SearchRaw(query string, request *SearchRequest) (*json.RawMessage, error)

GetTask(taskUID int64) (resp *Task, err error)
GetTasks(param *TasksQuery) (resp *TaskResult, err error)
Expand Down
97 changes: 65 additions & 32 deletions index_search.go
@@ -1,6 +1,7 @@
package meilisearch

import (
"encoding/json"
"net/http"
)

Expand All @@ -11,74 +12,106 @@ const (
DefaultLimit int64 = 20
)

func (i Index) SearchRaw(query string, request *SearchRequest) (*json.RawMessage, error) {
resp := &json.RawMessage{}

if request.Limit == 0 {
request.Limit = DefaultLimit
}

searchPostRequestParams := searchPostRequestParams(query, request)

req := internalRequest{
endpoint: "/indexes/" + i.UID + "/search",
method: http.MethodPost,
contentType: contentTypeJSON,
withRequest: searchPostRequestParams,
withResponse: resp,
acceptedStatusCodes: []int{http.StatusOK},
functionName: "SearchRaw",
}

if err := i.client.executeRequest(req); err != nil {
return nil, err
}

return resp, nil
}

func (i Index) Search(query string, request *SearchRequest) (*SearchResponse, error) {
resp := &SearchResponse{}

searchPostRequestParams := make(map[string]interface{}, 14)

if request.Limit == 0 {
request.Limit = DefaultLimit
}

searchPostRequestParams := searchPostRequestParams(query, request)

req := internalRequest{
endpoint: "/indexes/" + i.UID + "/search",
method: http.MethodPost,
contentType: contentTypeJSON,
withRequest: searchPostRequestParams,
withResponse: resp,
acceptedStatusCodes: []int{http.StatusOK},
functionName: "Search",
}

if err := i.client.executeRequest(req); err != nil {
return nil, err
}
Comment on lines +50 to +62
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this method can call directly SearchRaw and Unmarshal the result in SearchResponse to avoid duplicate code, WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah great point... I was essentially doing that in the unit test but not the actual implementation 😅 I'll take your suggestion and make that change


return resp, nil
}

func searchPostRequestParams(query string, request *SearchRequest) map[string]interface{} {
params := make(map[string]interface{}, 14)

if !request.PlaceholderSearch {
searchPostRequestParams["q"] = query
params["q"] = query
}
if request.Limit != DefaultLimit {
searchPostRequestParams["limit"] = request.Limit
params["limit"] = request.Limit
}
if request.ShowMatchesPosition {
searchPostRequestParams["showMatchesPosition"] = request.ShowMatchesPosition
params["showMatchesPosition"] = request.ShowMatchesPosition
}
if request.Filter != nil {
searchPostRequestParams["filter"] = request.Filter
params["filter"] = request.Filter
}
if request.Offset != 0 {
searchPostRequestParams["offset"] = request.Offset
params["offset"] = request.Offset
}
if request.CropLength != 0 {
searchPostRequestParams["cropLength"] = request.CropLength
params["cropLength"] = request.CropLength
}
if request.CropMarker != "" {
searchPostRequestParams["cropMarker"] = request.CropMarker
params["cropMarker"] = request.CropMarker
}
if request.HighlightPreTag != "" {
searchPostRequestParams["highlightPreTag"] = request.HighlightPreTag
params["highlightPreTag"] = request.HighlightPreTag
}
if request.HighlightPostTag != "" {
searchPostRequestParams["highlightPostTag"] = request.HighlightPostTag
params["highlightPostTag"] = request.HighlightPostTag
}
if request.MatchingStrategy != "" {
searchPostRequestParams["matchingStrategy"] = request.MatchingStrategy
params["matchingStrategy"] = request.MatchingStrategy
}
if len(request.AttributesToRetrieve) != 0 {
searchPostRequestParams["attributesToRetrieve"] = request.AttributesToRetrieve
params["attributesToRetrieve"] = request.AttributesToRetrieve
}
if len(request.AttributesToCrop) != 0 {
searchPostRequestParams["attributesToCrop"] = request.AttributesToCrop
params["attributesToCrop"] = request.AttributesToCrop
}
if len(request.AttributesToHighlight) != 0 {
searchPostRequestParams["attributesToHighlight"] = request.AttributesToHighlight
params["attributesToHighlight"] = request.AttributesToHighlight
}
if len(request.Facets) != 0 {
searchPostRequestParams["facets"] = request.Facets
params["facets"] = request.Facets
}
if len(request.Sort) != 0 {
searchPostRequestParams["sort"] = request.Sort
}

req := internalRequest{
endpoint: "/indexes/" + i.UID + "/search",
method: http.MethodPost,
contentType: contentTypeJSON,
withRequest: searchPostRequestParams,
withResponse: resp,
acceptedStatusCodes: []int{http.StatusOK},
functionName: "Search",
params["sort"] = request.Sort
}

if err := i.client.executeRequest(req); err != nil {
return nil, err
}

return resp, nil
return params
}
81 changes: 75 additions & 6 deletions index_search_test.go
@@ -1,11 +1,80 @@
package meilisearch

import (
"encoding/json"
"testing"

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

func TestIndex_SearchRaw(t *testing.T) {
type args struct {
UID string
PrimaryKey string
client *Client
query string
request SearchRequest
}

tests := []struct {
name string
args args
want *SearchResponse
}{
{
name: "TestIndexBasicSearch",
args: args{
UID: "indexUID",
client: defaultClient,
query: "prince",
request: SearchRequest{},
},
want: &SearchResponse{
Hits: []interface{}{
map[string]interface{}{
"book_id": float64(456), "title": "Le Petit Prince",
},
map[string]interface{}{
"Tag": "Epic fantasy", "book_id": float64(4), "title": "Harry Potter and the Half-Blood Prince",
},
},
EstimatedTotalHits: 2,
Offset: 0,
Limit: 20,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
SetUpIndexForFaceting()
c := tt.args.client
i := c.Index(tt.args.UID)
t.Cleanup(cleanup(c))

gotRaw, err := i.SearchRaw(tt.args.query, &tt.args.request)
require.NoError(t, err)

// Unmarshall the raw response from SearchRaw into a SearchResponse
var got SearchResponse
err = json.Unmarshal(*gotRaw, &got)
require.NoError(t, err, "error unmarshalling raw got SearchResponse")

require.Equal(t, len(tt.want.Hits), len(got.Hits))
for len := range got.Hits {
require.Equal(t, tt.want.Hits[len].(map[string]interface{})["title"], got.Hits[len].(map[string]interface{})["title"])
require.Equal(t, tt.want.Hits[len].(map[string]interface{})["book_id"], got.Hits[len].(map[string]interface{})["book_id"])
}
if tt.want.Hits[0].(map[string]interface{})["_formatted"] != nil {
require.Equal(t, tt.want.Hits[0].(map[string]interface{})["_formatted"], got.Hits[0].(map[string]interface{})["_formatted"])
}
require.Equal(t, tt.want.EstimatedTotalHits, got.EstimatedTotalHits)
require.Equal(t, tt.want.Offset, got.Offset)
require.Equal(t, tt.want.Limit, got.Limit)
require.Equal(t, tt.want.FacetDistribution, got.FacetDistribution)
})
}
}

func TestIndex_Search(t *testing.T) {
type args struct {
UID string
Expand Down Expand Up @@ -309,9 +378,9 @@ func TestIndex_Search(t *testing.T) {
client: defaultClient,
query: "le prince",
request: SearchRequest{
Limit: 10,
AttributesToRetrieve: []string{"book_id","title"},
MatchingStrategy: "all",
Limit: 10,
AttributesToRetrieve: []string{"book_id", "title"},
MatchingStrategy: "all",
},
},
want: &SearchResponse{
Expand All @@ -332,9 +401,9 @@ func TestIndex_Search(t *testing.T) {
client: defaultClient,
query: "prince",
request: SearchRequest{
Limit: 10,
AttributesToRetrieve: []string{"book_id","title"},
MatchingStrategy: "last",
Limit: 10,
AttributesToRetrieve: []string{"book_id", "title"},
MatchingStrategy: "last",
},
},
want: &SearchResponse{
Expand Down