From 1329aa51b605cb54ba9aae3a82a0a87b881fb7b3 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Mon, 13 Nov 2017 09:09:58 -0800 Subject: Updating server dependancies. (#7816) --- vendor/gopkg.in/olivere/elastic.v5/.travis.yml | 2 +- vendor/gopkg.in/olivere/elastic.v5/CONTRIBUTORS | 6 ++ vendor/gopkg.in/olivere/elastic.v5/bulk.go | 2 +- vendor/gopkg.in/olivere/elastic.v5/bulk_test.go | 27 +++++ vendor/gopkg.in/olivere/elastic.v5/client.go | 13 ++- .../gopkg.in/olivere/elastic.v5/docker-compose.yml | 2 +- .../gopkg.in/olivere/elastic.v5/indices_refresh.go | 12 +-- vendor/gopkg.in/olivere/elastic.v5/msearch.go | 2 +- vendor/gopkg.in/olivere/elastic.v5/request_test.go | 14 +++ vendor/gopkg.in/olivere/elastic.v5/response.go | 4 +- .../gopkg.in/olivere/elastic.v5/response_test.go | 48 +++++++++ vendor/gopkg.in/olivere/elastic.v5/run-es-5.6.3.sh | 2 + vendor/gopkg.in/olivere/elastic.v5/search.go | 31 +++--- .../gopkg.in/olivere/elastic.v5/search_request.go | 9 +- .../olivere/elastic.v5/search_suggester_test.go | 106 +++++++++++++++++++ vendor/gopkg.in/olivere/elastic.v5/setup_test.go | 8 +- .../olivere/elastic.v5/suggester_context.go | 113 +++++++++++++++++++++ .../olivere/elastic.v5/suggester_context_test.go | 55 ++++++++++ 18 files changed, 418 insertions(+), 38 deletions(-) create mode 100644 vendor/gopkg.in/olivere/elastic.v5/response_test.go create mode 100755 vendor/gopkg.in/olivere/elastic.v5/run-es-5.6.3.sh create mode 100644 vendor/gopkg.in/olivere/elastic.v5/suggester_context_test.go (limited to 'vendor/gopkg.in/olivere') diff --git a/vendor/gopkg.in/olivere/elastic.v5/.travis.yml b/vendor/gopkg.in/olivere/elastic.v5/.travis.yml index 703fa01be..6f718f66a 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/.travis.yml +++ b/vendor/gopkg.in/olivere/elastic.v5/.travis.yml @@ -12,5 +12,5 @@ services: - docker before_install: - sudo sysctl -w vm.max_map_count=262144 - - docker run --rm --privileged=true -p 9200:9200 -p 9300:9300 -e "bootstrap.memory_lock=true" -e "ES_JAVA_OPTS=-Xms1g -Xmx1g" docker.elastic.co/elasticsearch/elasticsearch:5.6.1 elasticsearch -Expack.security.enabled=false -Escript.inline=true -Escript.stored=true -Escript.file=true -Enetwork.host=_local_,_site_ -Enetwork.publish_host=_local_ >& /dev/null & + - docker run --rm --privileged=true -p 9200:9200 -p 9300:9300 -e "bootstrap.memory_lock=true" -e "ES_JAVA_OPTS=-Xms1g -Xmx1g" docker.elastic.co/elasticsearch/elasticsearch:5.6.3 elasticsearch -Expack.security.enabled=false -Escript.inline=true -Escript.stored=true -Escript.file=true -Enetwork.host=_local_,_site_ -Enetwork.publish_host=_local_ >& /dev/null & - sleep 30 diff --git a/vendor/gopkg.in/olivere/elastic.v5/CONTRIBUTORS b/vendor/gopkg.in/olivere/elastic.v5/CONTRIBUTORS index 572caf62d..e3ded87cd 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/CONTRIBUTORS +++ b/vendor/gopkg.in/olivere/elastic.v5/CONTRIBUTORS @@ -20,6 +20,7 @@ Andrew Dunham [@andrew-d](https://github.com/andrew-d) Andrew Gaul [@andrewgaul](https://github.com/andrewgaul) Andy Walker [@alaska](https://github.com/alaska) Arquivei [@arquivei](https://github.com/arquivei) +arthurgustin [@arthurgustin](https://github.com/arthurgustin) Benjamin Fernandes [@LotharSee](https://github.com/LotharSee) Benjamin Zarzycki [@kf6nux](https://github.com/kf6nux) Braden Bassingthwaite [@bbassingthwaite-va](https://github.com/bbassingthwaite-va) @@ -65,13 +66,16 @@ Joe Buck [@four2five](https://github.com/four2five) John Barker [@j16r](https://github.com/j16r) John Goodall [@jgoodall](https://github.com/jgoodall) John Stanford [@jxstanford](https://github.com/jxstanford) +Josh Chorlton [@jchorl](https://github.com/jchorl) jun [@coseyo](https://github.com/coseyo) Junpei Tsuji [@jun06t](https://github.com/jun06t) Keith Hatton [@khatton-ft](https://github.com/khatton-ft) +kel [@liketic](https://github.com/liketic) Kenta SUZUKI [@suzuken](https://github.com/suzuken) Kevin Mulvey [@kmulvey](https://github.com/kmulvey) Kyle Brandt [@kylebrandt](https://github.com/kylebrandt) Leandro Piccilli [@lpic10](https://github.com/lpic10) +M. Zulfa Achsani [@misterciput](https://github.com/misterciput) Maciej Lisiewski [@c2h5oh](https://github.com/c2h5oh) Mara Kim [@autochthe](https://github.com/autochthe) Marcy Buccellato [@marcybuccellato](https://github.com/marcybuccellato) @@ -88,6 +92,7 @@ Nick K [@utrack](https://github.com/utrack) Nick Whyte [@nickw444](https://github.com/nickw444) Nicolae Vartolomei [@nvartolomei](https://github.com/nvartolomei) Orne Brocaar [@brocaar](https://github.com/brocaar) +Paul [@eyeamera](https://github.com/eyeamera) Pete C [@peteclark-ft](https://github.com/peteclark-ft) Radoslaw Wesolowski [r--w](https://github.com/r--w) Ryan Schmukler [@rschmukler](https://github.com/rschmukler) @@ -110,4 +115,5 @@ Wyndham Blanton [@wyndhblb](https://github.com/wyndhblb) Yarden Bar [@ayashjorden](https://github.com/ayashjorden) zakthomas [@zakthomas](https://github.com/zakthomas) singham [@zhaochenxiao90](https://github.com/zhaochenxiao90) +@林 [@zplzpl](https://github.com/zplzpl) Roman Colohanin [@zuzmic](https://github.com/zuzmic) diff --git a/vendor/gopkg.in/olivere/elastic.v5/bulk.go b/vendor/gopkg.in/olivere/elastic.v5/bulk.go index eac240ddb..f2fa0ea73 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/bulk.go +++ b/vendor/gopkg.in/olivere/elastic.v5/bulk.go @@ -234,7 +234,7 @@ func (s *BulkService) Do(ctx context.Context) (*BulkResponse, error) { } // Get response - res, err := s.client.PerformRequest(ctx, "POST", path, params, body) + res, err := s.client.PerformRequestWithContentType(ctx, "POST", path, params, body, "application/x-ndjson") if err != nil { return nil, err } diff --git a/vendor/gopkg.in/olivere/elastic.v5/bulk_test.go b/vendor/gopkg.in/olivere/elastic.v5/bulk_test.go index fba52be73..394439630 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/bulk_test.go +++ b/vendor/gopkg.in/olivere/elastic.v5/bulk_test.go @@ -7,6 +7,9 @@ package elastic import ( "context" "encoding/json" + "fmt" + "net/http" + "net/http/httptest" "testing" ) @@ -505,3 +508,27 @@ func BenchmarkBulkEstimatedSizeInBytesWith100Requests(b *testing.B) { b.ReportAllocs() benchmarkBulkEstimatedSizeInBytes = result // ensure the compiler doesn't optimize } + +func TestBulkContentType(t *testing.T) { + var header http.Header + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + header = r.Header + fmt.Fprintln(w, `{}`) + })) + defer ts.Close() + + client, err := NewSimpleClient(SetURL(ts.URL)) + if err != nil { + t.Fatal(err) + } + indexReq := NewBulkIndexRequest().Index(testIndexName).Type("tweet").Id("1").Doc(tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."}) + if _, err := client.Bulk().Add(indexReq).Do(context.Background()); err != nil { + t.Fatal(err) + } + if header == nil { + t.Fatalf("expected header, got %v", header) + } + if want, have := "application/x-ndjson", header.Get("Content-Type"); want != have { + t.Fatalf("Content-Type: want %q, have %q", want, have) + } +} diff --git a/vendor/gopkg.in/olivere/elastic.v5/client.go b/vendor/gopkg.in/olivere/elastic.v5/client.go index 13b45d831..9a48d9ac7 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/client.go +++ b/vendor/gopkg.in/olivere/elastic.v5/client.go @@ -26,7 +26,7 @@ import ( const ( // Version is the current version of Elastic. - Version = "5.0.48" + Version = "5.0.53" // DefaultURL is the default endpoint of Elasticsearch on the local machine. // It is used e.g. when initializing a new Client without a specific URL. @@ -1168,12 +1168,18 @@ func (c *Client) mustActiveConn() error { } // PerformRequest does a HTTP request to Elasticsearch. +// See PerformRequestWithContentType for details. +func (c *Client) PerformRequest(ctx context.Context, method, path string, params url.Values, body interface{}, ignoreErrors ...int) (*Response, error) { + return c.PerformRequestWithContentType(ctx, method, path, params, body, "application/json", ignoreErrors...) +} + +// PerformRequestWithContentType executes a HTTP request with a specific content type. // It returns a response (which might be nil) and an error on failure. // // Optionally, a list of HTTP error codes to ignore can be passed. // This is necessary for services that expect e.g. HTTP status 404 as a // valid outcome (Exists, IndicesExists, IndicesTypeExists). -func (c *Client) PerformRequest(ctx context.Context, method, path string, params url.Values, body interface{}, ignoreErrors ...int) (*Response, error) { +func (c *Client) PerformRequestWithContentType(ctx context.Context, method, path string, params url.Values, body interface{}, contentType string, ignoreErrors ...int) (*Response, error) { start := time.Now().UTC() c.mu.RLock() @@ -1236,6 +1242,9 @@ func (c *Client) PerformRequest(ctx context.Context, method, path string, params if basicAuth { req.SetBasicAuth(basicAuthUsername, basicAuthPassword) } + if contentType != "" { + req.Header.Set("Content-Type", contentType) + } // Set body if body != nil { diff --git a/vendor/gopkg.in/olivere/elastic.v5/docker-compose.yml b/vendor/gopkg.in/olivere/elastic.v5/docker-compose.yml index 046096db2..002eac7fa 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/docker-compose.yml +++ b/vendor/gopkg.in/olivere/elastic.v5/docker-compose.yml @@ -2,7 +2,7 @@ version: '3' services: elasticsearch: - image: docker.elastic.co/elasticsearch/elasticsearch:5.6.0 + image: docker.elastic.co/elasticsearch/elasticsearch:5.6.3 # container_name: elasticsearch hostname: elasticsearch environment: diff --git a/vendor/gopkg.in/olivere/elastic.v5/indices_refresh.go b/vendor/gopkg.in/olivere/elastic.v5/indices_refresh.go index 79324d75f..dbc83ac2c 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/indices_refresh.go +++ b/vendor/gopkg.in/olivere/elastic.v5/indices_refresh.go @@ -14,11 +14,10 @@ import ( ) // RefreshService explicitly refreshes one or more indices. -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/indices-refresh.html. +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/indices-refresh.html. type RefreshService struct { client *Client index []string - force *bool pretty bool } @@ -36,12 +35,6 @@ func (s *RefreshService) Index(index ...string) *RefreshService { return s } -// Force forces a refresh. -func (s *RefreshService) Force(force bool) *RefreshService { - s.force = &force - return s -} - // Pretty asks Elasticsearch to return indented JSON. func (s *RefreshService) Pretty(pretty bool) *RefreshService { s.pretty = pretty @@ -66,9 +59,6 @@ func (s *RefreshService) buildURL() (string, url.Values, error) { // Add query string parameters params := url.Values{} - if s.force != nil { - params.Set("force", fmt.Sprintf("%v", *s.force)) - } if s.pretty { params.Set("pretty", fmt.Sprintf("%v", s.pretty)) } diff --git a/vendor/gopkg.in/olivere/elastic.v5/msearch.go b/vendor/gopkg.in/olivere/elastic.v5/msearch.go index 52ca9ee74..5d0949d9c 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/msearch.go +++ b/vendor/gopkg.in/olivere/elastic.v5/msearch.go @@ -68,7 +68,7 @@ func (s *MultiSearchService) Do(ctx context.Context) (*MultiSearchResult, error) if err != nil { return nil, err } - body, err := json.Marshal(sr.body()) + body, err := json.Marshal(sr.Body()) if err != nil { return nil, err } diff --git a/vendor/gopkg.in/olivere/elastic.v5/request_test.go b/vendor/gopkg.in/olivere/elastic.v5/request_test.go index 2a2d229df..d5ae4f800 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/request_test.go +++ b/vendor/gopkg.in/olivere/elastic.v5/request_test.go @@ -8,6 +8,20 @@ import "testing" var testReq *Request // used as a temporary variable to avoid compiler optimizations in tests/benchmarks +func TestRequestSetContentType(t *testing.T) { + req, err := NewRequest("GET", "/") + if err != nil { + t.Fatal(err) + } + if want, have := "application/json", req.Header.Get("Content-Type"); want != have { + t.Fatalf("want %q, have %q", want, have) + } + req.Header.Set("Content-Type", "application/x-ndjson") + if want, have := "application/x-ndjson", req.Header.Get("Content-Type"); want != have { + t.Fatalf("want %q, have %q", want, have) + } +} + func BenchmarkRequestSetBodyString(b *testing.B) { req, err := NewRequest("GET", "/") if err != nil { diff --git a/vendor/gopkg.in/olivere/elastic.v5/response.go b/vendor/gopkg.in/olivere/elastic.v5/response.go index e7380d98a..4fcdc32d6 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/response.go +++ b/vendor/gopkg.in/olivere/elastic.v5/response.go @@ -34,9 +34,7 @@ func (c *Client) newResponse(res *http.Response) (*Response, error) { } // HEAD requests return a body but no content if len(slurp) > 0 { - if err := c.decoder.Decode(slurp, &r.Body); err != nil { - return nil, err - } + r.Body = json.RawMessage(slurp) } } return r, nil diff --git a/vendor/gopkg.in/olivere/elastic.v5/response_test.go b/vendor/gopkg.in/olivere/elastic.v5/response_test.go new file mode 100644 index 000000000..e62773403 --- /dev/null +++ b/vendor/gopkg.in/olivere/elastic.v5/response_test.go @@ -0,0 +1,48 @@ +// Copyright 2012-present Oliver Eilhard. All rights reserved. +// Use of this source code is governed by a MIT-license. +// See http://olivere.mit-license.org/license.txt for details. + +package elastic + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "testing" +) + +func BenchmarkResponse(b *testing.B) { + c := &Client{ + decoder: &DefaultDecoder{}, + } + + var resp *Response + for n := 0; n < b.N; n++ { + iteration := fmt.Sprint(n) + body := fmt.Sprintf(`{"n":%d}`, n) + res := &http.Response{ + Header: http.Header{ + "X-Iteration": []string{iteration}, + }, + Body: ioutil.NopCloser(bytes.NewBufferString(body)), + StatusCode: http.StatusOK, + } + var err error + resp, err = c.newResponse(res) + if err != nil { + b.Fatal(err) + } + /* + if want, have := body, string(resp.Body); want != have { + b.Fatalf("want %q, have %q", want, have) + } + //*/ + /* + if want, have := iteration, resp.Header.Get("X-Iteration"); want != have { + b.Fatalf("want %q, have %q", want, have) + } + //*/ + } + _ = resp +} diff --git a/vendor/gopkg.in/olivere/elastic.v5/run-es-5.6.3.sh b/vendor/gopkg.in/olivere/elastic.v5/run-es-5.6.3.sh new file mode 100755 index 000000000..6a9864668 --- /dev/null +++ b/vendor/gopkg.in/olivere/elastic.v5/run-es-5.6.3.sh @@ -0,0 +1,2 @@ +VERSION=5.6.3 +docker run --rm --privileged=true -p 9200:9200 -p 9300:9300 -v "$PWD/etc:/usr/share/elasticsearch/config" -e "bootstrap.memory_lock=true" -e "ES_JAVA_OPTS=-Xms1g -Xmx1g" docker.elastic.co/elasticsearch/elasticsearch:$VERSION elasticsearch -Expack.security.enabled=false -Escript.inline=true -Escript.stored=true -Escript.file=true diff --git a/vendor/gopkg.in/olivere/elastic.v5/search.go b/vendor/gopkg.in/olivere/elastic.v5/search.go index 301550815..7121d5545 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/search.go +++ b/vendor/gopkg.in/olivere/elastic.v5/search.go @@ -60,7 +60,7 @@ func (s *SearchService) Source(source interface{}) *SearchService { // FilterPath allows reducing the response, a mechanism known as // response filtering and described here: -// https://www.elastic.co/guide/en/elasticsearch/reference/5.2/common-options.html#common-options-response-filtering. +// https://www.elastic.co/guide/en/elasticsearch/reference/5.6/common-options.html#common-options-response-filtering. func (s *SearchService) FilterPath(filterPath ...string) *SearchService { s.filterPath = append(s.filterPath, filterPath...) return s @@ -113,7 +113,7 @@ func (s *SearchService) TimeoutInMillis(timeoutInMillis int) *SearchService { // SearchType sets the search operation type. Valid values are: // "query_then_fetch", "query_and_fetch", "dfs_query_then_fetch", // "dfs_query_and_fetch", "count", "scan". -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-request-search-type.html +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-search-type.html // for details. func (s *SearchService) SearchType(searchType string) *SearchService { s.searchType = searchType @@ -271,7 +271,7 @@ func (s *SearchService) StoredFields(fields ...string) *SearchService { // SearchAfter allows a different form of pagination by using a live cursor, // using the results of the previous page to help the retrieval of the next. // -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-request-search-after.html +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-search-after.html func (s *SearchService) SearchAfter(sortValues ...interface{}) *SearchService { s.searchSource = s.searchSource.SearchAfter(sortValues...) return s @@ -473,7 +473,7 @@ type SearchHitInnerHits struct { } // SearchExplanation explains how the score for a hit was computed. -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-request-explain.html. +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-explain.html. type SearchExplanation struct { Value float64 `json:"value"` // e.g. 1.0 Description string `json:"description"` // e.g. "boost" or "ConstantScore(*:*), product of:" @@ -483,11 +483,11 @@ type SearchExplanation struct { // Suggest // SearchSuggest is a map of suggestions. -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-suggesters.html. +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-suggesters.html. type SearchSuggest map[string][]SearchSuggestion // SearchSuggestion is a single search suggestion. -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-suggesters.html. +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-suggesters.html. type SearchSuggestion struct { Text string `json:"text"` Offset int `json:"offset"` @@ -496,14 +496,17 @@ type SearchSuggestion struct { } // SearchSuggestionOption is an option of a SearchSuggestion. -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-suggesters.html. +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-suggesters.html. type SearchSuggestionOption struct { - Text string `json:"text"` - Index string `json:"_index"` - Type string `json:"_type"` - Id string `json:"_id"` - Score float64 `json:"_score"` - Source *json.RawMessage `json:"_source"` + Text string `json:"text"` + Index string `json:"_index"` + Type string `json:"_type"` + Id string `json:"_id"` + Score float64 `json:"score"` + Highlighted string `json:"highlighted"` + CollateMatch bool `json:"collate_match"` + Freq int `json:"freq"` // from TermSuggestion.Option in Java API + Source *json.RawMessage `json:"_source"` } // SearchProfile is a list of shard profiling data collected during @@ -556,6 +559,6 @@ type ProfileResult struct { // Highlighting // SearchHitHighlight is the highlight information of a search hit. -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-request-highlighting.html +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-request-highlighting.html // for a general discussion of highlighting. type SearchHitHighlight map[string][]string diff --git a/vendor/gopkg.in/olivere/elastic.v5/search_request.go b/vendor/gopkg.in/olivere/elastic.v5/search_request.go index ad22a5a3f..03513085f 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/search_request.go +++ b/vendor/gopkg.in/olivere/elastic.v5/search_request.go @@ -194,9 +194,12 @@ func (r *SearchRequest) header() interface{} { return h } -// body is used by MultiSearch to get information about the search body +// Body allows to access the search body of the request, as generated by the DSL. +// Notice that Body is read-only. You must not change the request body. +// +// Body is used e.g. by MultiSearch to get information about the search body // of one SearchRequest. -// See https://www.elastic.co/guide/en/elasticsearch/reference/5.2/search-multi-search.html -func (r *SearchRequest) body() interface{} { +// See https://www.elastic.co/guide/en/elasticsearch/reference/5.6/search-multi-search.html +func (r *SearchRequest) Body() interface{} { return r.source } diff --git a/vendor/gopkg.in/olivere/elastic.v5/search_suggester_test.go b/vendor/gopkg.in/olivere/elastic.v5/search_suggester_test.go index 78232e9d6..a555e3462 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/search_suggester_test.go +++ b/vendor/gopkg.in/olivere/elastic.v5/search_suggester_test.go @@ -238,3 +238,109 @@ func TestCompletionSuggester(t *testing.T) { t.Errorf("expected Text = 'Golang'; got %s", myOption.Text) } } + +func TestContextSuggester(t *testing.T) { + client := setupTestClientAndCreateIndex(t) // , SetTraceLog(log.New(os.Stdout, "", 0))) + + // TODO make a nice way of creating tweets, as currently the context fields are unsupported as part of the suggestion fields + tweet1 := ` + { + "user":"olivere", + "message":"Welcome to Golang and Elasticsearch.", + "retweets":0, + "created":"0001-01-01T00:00:00Z", + "suggest_field":{ + "input":[ + "Golang", + "Elasticsearch" + ], + "contexts":{ + "user_name": ["olivere"] + } + } + } + ` + tweet2 := ` + { + "user":"sandrae", + "message":"I like golfing", + "retweets":0, + "created":"0001-01-01T00:00:00Z", + "suggest_field":{ + "input":[ + "Golfing" + ], + "contexts":{ + "user_name": ["sandrae"] + } + } + } + ` + + // Add all documents + _, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyString(tweet1).Do(context.TODO()) + if err != nil { + t.Fatal(err) + } + + _, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyString(tweet2).Do(context.TODO()) + if err != nil { + t.Fatal(err) + } + + _, err = client.Flush().Index(testIndexName).Do(context.TODO()) + if err != nil { + t.Fatal(err) + } + + suggesterName := "my-suggestions" + cs := NewContextSuggester(suggesterName) + cs = cs.Prefix("Gol") + cs = cs.Field("suggest_field") + cs = cs.ContextQueries( + NewSuggesterCategoryQuery("user_name", "olivere"), + ) + + searchResult, err := client.Search(). + Index(testIndexName). + Suggester(cs). + Do(context.TODO()) + if err != nil { + t.Fatal(err) + } + if searchResult.Suggest == nil { + t.Errorf("expected SearchResult.Suggest != nil; got nil") + } + mySuggestions, found := searchResult.Suggest[suggesterName] + if !found { + t.Errorf("expected to find SearchResult.Suggest[%s]; got false", suggesterName) + } + if mySuggestions == nil { + t.Errorf("expected SearchResult.Suggest[%s] != nil; got nil", suggesterName) + } + + // sandra's tweet is not returned because of the user_name context + if len(mySuggestions) != 1 { + t.Errorf("expected 1 suggestion; got %d", len(mySuggestions)) + } + mySuggestion := mySuggestions[0] + if mySuggestion.Text != "Gol" { + t.Errorf("expected Text = 'Gol'; got %s", mySuggestion.Text) + } + if mySuggestion.Offset != 0 { + t.Errorf("expected Offset = %d; got %d", 0, mySuggestion.Offset) + } + if mySuggestion.Length != 3 { + t.Errorf("expected Length = %d; got %d", 3, mySuggestion.Length) + } + if len(mySuggestion.Options) != 1 { + t.Errorf("expected 1 option; got %d", len(mySuggestion.Options)) + } + myOption := mySuggestion.Options[0] + if myOption.Text != "Golang" { + t.Errorf("expected Text = 'Golang'; got %s", myOption.Text) + } + if myOption.Id != "1" { + t.Errorf("expected Id = '1'; got %s", myOption.Id) + } +} diff --git a/vendor/gopkg.in/olivere/elastic.v5/setup_test.go b/vendor/gopkg.in/olivere/elastic.v5/setup_test.go index 7e449c821..df2206a14 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/setup_test.go +++ b/vendor/gopkg.in/olivere/elastic.v5/setup_test.go @@ -45,7 +45,13 @@ const ( "type":"geo_point" }, "suggest_field":{ - "type":"completion" + "type":"completion", + "contexts":[ + { + "name": "user_name", + "type": "category" + } + ] } } }, diff --git a/vendor/gopkg.in/olivere/elastic.v5/suggester_context.go b/vendor/gopkg.in/olivere/elastic.v5/suggester_context.go index caf477669..ade099151 100644 --- a/vendor/gopkg.in/olivere/elastic.v5/suggester_context.go +++ b/vendor/gopkg.in/olivere/elastic.v5/suggester_context.go @@ -4,8 +4,121 @@ package elastic +import "errors" + // SuggesterContextQuery is used to define context information within // a suggestion request. type SuggesterContextQuery interface { Source() (interface{}, error) } + +// ContextSuggester is a fast suggester for e.g. type-ahead completion that supports filtering and boosting based on contexts. +// See https://www.elastic.co/guide/en/elasticsearch/reference/current/suggester-context.html +// for more details. +type ContextSuggester struct { + Suggester + name string + prefix string + field string + size *int + contextQueries []SuggesterContextQuery +} + +// Creates a new context suggester. +func NewContextSuggester(name string) *ContextSuggester { + return &ContextSuggester{ + name: name, + contextQueries: make([]SuggesterContextQuery, 0), + } +} + +func (q *ContextSuggester) Name() string { + return q.name +} + +func (q *ContextSuggester) Prefix(prefix string) *ContextSuggester { + q.prefix = prefix + return q +} + +func (q *ContextSuggester) Field(field string) *ContextSuggester { + q.field = field + return q +} + +func (q *ContextSuggester) Size(size int) *ContextSuggester { + q.size = &size + return q +} + +func (q *ContextSuggester) ContextQuery(query SuggesterContextQuery) *ContextSuggester { + q.contextQueries = append(q.contextQueries, query) + return q +} + +func (q *ContextSuggester) ContextQueries(queries ...SuggesterContextQuery) *ContextSuggester { + q.contextQueries = append(q.contextQueries, queries...) + return q +} + +// contextSuggesterRequest is necessary because the order in which +// the JSON elements are routed to Elasticsearch is relevant. +// We got into trouble when using plain maps because the text element +// needs to go before the completion element. +type contextSuggesterRequest struct { + Prefix string `json:"prefix"` + Completion interface{} `json:"completion"` +} + +// Creates the source for the context suggester. +func (q *ContextSuggester) Source(includeName bool) (interface{}, error) { + cs := &contextSuggesterRequest{} + + if q.prefix != "" { + cs.Prefix = q.prefix + } + + suggester := make(map[string]interface{}) + cs.Completion = suggester + + if q.field != "" { + suggester["field"] = q.field + } + if q.size != nil { + suggester["size"] = *q.size + } + switch len(q.contextQueries) { + case 0: + case 1: + src, err := q.contextQueries[0].Source() + if err != nil { + return nil, err + } + suggester["context"] = src + default: + ctxq := make(map[string]interface{}) + for _, query := range q.contextQueries { + src, err := query.Source() + if err != nil { + return nil, err + } + // Merge the dictionary into ctxq + m, ok := src.(map[string]interface{}) + if !ok { + return nil, errors.New("elastic: context query is not a map") + } + for k, v := range m { + ctxq[k] = v + } + } + suggester["contexts"] = ctxq + } + + if !includeName { + return cs, nil + } + + source := make(map[string]interface{}) + source[q.name] = cs + return source, nil +} diff --git a/vendor/gopkg.in/olivere/elastic.v5/suggester_context_test.go b/vendor/gopkg.in/olivere/elastic.v5/suggester_context_test.go new file mode 100644 index 000000000..cd3c5586c --- /dev/null +++ b/vendor/gopkg.in/olivere/elastic.v5/suggester_context_test.go @@ -0,0 +1,55 @@ +// Copyright 2012-present Oliver Eilhard. All rights reserved. +// Use of this source code is governed by a MIT-license. +// See http://olivere.mit-license.org/license.txt for details. + +package elastic + +import ( + "encoding/json" + "testing" +) + +func TestContextSuggesterSource(t *testing.T) { + s := NewContextSuggester("place_suggestion"). + Prefix("tim"). + Field("suggest") + src, err := s.Source(true) + if err != nil { + t.Fatal(err) + } + data, err := json.Marshal(src) + if err != nil { + t.Fatalf("marshaling to JSON failed: %v", err) + } + got := string(data) + expected := `{"place_suggestion":{"prefix":"tim","completion":{"field":"suggest"}}}` + if got != expected { + t.Errorf("expected\n%s\n,got:\n%s", expected, got) + } +} + +func TestContextSuggesterSourceWithMultipleContexts(t *testing.T) { + s := NewContextSuggester("place_suggestion"). + Prefix("tim"). + Field("suggest"). + ContextQueries( + NewSuggesterCategoryQuery("place_type", "cafe", "restaurants"), + ) + src, err := s.Source(true) + if err != nil { + t.Fatal(err) + } + data, err := json.Marshal(src) + if err != nil { + t.Fatalf("marshaling to JSON failed: %v", err) + } + got := string(data) + // Due to the randomization of dictionary key, we could actually have two different valid expected outcomes + expected := `{"place_suggestion":{"prefix":"tim","completion":{"context":{"place_type":[{"context":"cafe"},{"context":"restaurants"}]},"field":"suggest"}}}` + if got != expected { + expected := `{"place_suggestion":{"prefix":"tim","completion":{"context":{"place_type":[{"context":"restaurants"},{"context":"cafe"}]},"field":"suggest"}}}` + if got != expected { + t.Errorf("expected %s\n,got:\n%s", expected, got) + } + } +} -- cgit v1.2.3-1-g7c22