Open karmi opened 4 years ago
Hey @karmi, I'm interested in implementing the mentioned features. Would you please guide me from where should I start? I'm determined but new here. I'd love to work on this issue. Thanks.
Hello, thanks for the offer. I'm not sure that this issue is best for starting with adding features to the package. It assumes a lot of familiarity with Elasticsearch and common usage patterns, figuring out how to keep any supporting structures in sync with the Elasticsearch response format evolution, and so on. A more approachable "good first issue" is adding support for metadata to the bulk indexing helper, see eg. https://github.com/elastic/go-elasticsearch/issues/175 and related issues / pull requests. (That said, if you want to play with the feature, I can look at patches, of course.)
Thanks for the Suggestion. Yeah, it's better to contribute to a few good first issues first. Thanks.
The client should provide a high-level helper component for convenient, efficient handling of search results.
It should provide the following facilities:
_source
fieldsort
,highlight
, ...)Example:
Example implementation
```golang package main import ( "context" "encoding/json" "fmt" "io" "log" "os" "strings" "github.com/elastic/go-elasticsearch/v8" "github.com/elastic/go-elasticsearch/v8/estransport" "github.com/elastic/go-elasticsearch/v8/esutil" ) func main() { log.SetFlags(0) var indexName = "test-search" es, _ := elasticsearch.NewClient(elasticsearch.Config{ Logger: &estransport.ColorLogger{ Output: os.Stdout, EnableRequestBody: false, EnableResponseBody: false, }, }) bi, err := esutil.NewBulkIndexer(esutil.BulkIndexerConfig{ Index: indexName, Client: es, }) if err != nil { log.Fatalf("Error creating the indexer: %s", err) } log.Println("Indexing the documents...") es.Indices.Delete([]string{indexName}) for i := 1; i <= 15; i++ { bi.Add( context.Background(), esutil.BulkIndexerItem{ Action: "index", Body: strings.NewReader(fmt.Sprintf(`{"title" : "Test %03d"}`, i)), }, ) } bi.Close(context.Background()) es.Indices.Refresh(es.Indices.Refresh.WithIndex(indexName)) log.Println(strings.Repeat("-", 80)) log.Println("Searching the index...") res, err := es.Search( es.Search.WithIndex(indexName), es.Search.WithSize(12), ) if err != nil { log.Fatalf("ERROR: %s", err) } defer res.Body.Close() if res.IsError() { log.Fatalf("ERROR: %s", res.Status()) } results, err := NewSearchResponse(res.Body) if err != nil { log.Fatalf("ERROR: %s", err) } log.Println("Total hits:", results.Hits.Total()) for results.Hits.Next() { item := results.Hits.Item() fmt.Printf("* %s \n", item.Source["title"]) } } // ---------------------------------------------------------------------------- func NewSearchResponse(body io.Reader) (SearchResponse, error) { var response = SearchResponse{ body: body, Hits: &SearchResponseHits{}, } var r envelopeResponse if err := json.NewDecoder(body).Decode(&r); err != nil { return response, err } response.Hits.total = r.Hits.Total.Value for _, h := range r.Hits.Hits { var hit SearchResponseHit hit.ID = h.ID hit.Index = h.Index hit.Source = make(map[string]interface{}) if err := json.Unmarshal(h.Source, &hit.Source); err != nil { return response, err } response.Hits.append(hit) } return response, nil } type SearchResponse struct { body io.Reader Hits *SearchResponseHits } type SearchResponseHits struct { hits []SearchResponseHit total int currentIndex int } type SearchResponseHit struct { Index string ID string Source map[string]interface{} } func (h *SearchResponseHits) Total() int { return h.total } func (h *SearchResponseHits) Next() bool { if h.currentIndex < len(h.hits) { h.currentIndex++ return true } h.currentIndex = 0 return false } func (h *SearchResponseHits) Item() SearchResponseHit { return h.hits[h.currentIndex-1] } func (h *SearchResponseHits) append(hit SearchResponseHit) { h.hits = append(h.hits, hit) } type envelopeResponse struct { Took int Hits struct { Total struct{ Value int } Hits []struct { Index string `json:"_index"` ID string `json:"_id"` Source json.RawMessage `json:"_source"` } } } ```