You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1370 lines
38 KiB
1370 lines
38 KiB
// 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 ( |
|
"context" |
|
"encoding/json" |
|
"reflect" |
|
"testing" |
|
"time" |
|
) |
|
|
|
func TestSearchMatchAll(t *testing.T) { |
|
//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags))) |
|
client := setupTestClientAndCreateIndexAndAddDocs(t) |
|
|
|
// Match all should return all documents |
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(NewMatchAllQuery()). |
|
Size(100). |
|
Pretty(true). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if got, want := searchResult.Hits.TotalHits, int64(12); got != want { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", want, got) |
|
} |
|
if got, want := len(searchResult.Hits.Hits), 12; got != want { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, got) |
|
} |
|
|
|
for _, hit := range searchResult.Hits.Hits { |
|
if hit.Index != testIndexName { |
|
t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index) |
|
} |
|
item := make(map[string]interface{}) |
|
err := json.Unmarshal(*hit.Source, &item) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchMatchAllWithRequestCacheDisabled(t *testing.T) { |
|
//client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags))) |
|
client := setupTestClientAndCreateIndexAndAddDocs(t) |
|
|
|
// Match all should return all documents, with request cache disabled |
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(NewMatchAllQuery()). |
|
Size(100). |
|
Pretty(true). |
|
RequestCache(false). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if got, want := searchResult.Hits.TotalHits, int64(12); got != want { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", want, got) |
|
} |
|
if got, want := len(searchResult.Hits.Hits), 12; got != want { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, got) |
|
} |
|
} |
|
|
|
func BenchmarkSearchMatchAll(b *testing.B) { |
|
client := setupTestClientAndCreateIndexAndAddDocs(b) |
|
|
|
for n := 0; n < b.N; n++ { |
|
// Match all should return all documents |
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO()) |
|
if err != nil { |
|
b.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
b.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits == 0 { |
|
b.Errorf("expected SearchResult.Hits.TotalHits > %d; got %d", 0, searchResult.Hits.TotalHits) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchResultTotalHits(t *testing.T) { |
|
client := setupTestClientAndCreateIndexAndAddDocs(t) |
|
|
|
count, err := client.Count(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
got := searchResult.TotalHits() |
|
if got != count { |
|
t.Fatalf("expected %d hits; got: %d", count, got) |
|
} |
|
|
|
// No hits |
|
searchResult = &SearchResult{} |
|
got = searchResult.TotalHits() |
|
if got != 0 { |
|
t.Errorf("expected %d hits; got: %d", 0, got) |
|
} |
|
} |
|
|
|
func TestSearchResultWithProfiling(t *testing.T) { |
|
client := setupTestClientAndCreateIndexAndAddDocs(t) |
|
|
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search().Index(testIndexName).Query(all).Profile(true).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
if searchResult.Profile == nil { |
|
t.Fatal("Profiled MatchAll query did not return profiling data with results") |
|
} |
|
} |
|
|
|
func TestSearchResultEach(t *testing.T) { |
|
client := setupTestClientAndCreateIndexAndAddDocs(t) |
|
|
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search().Index(testIndexName).Query(all).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
// Iterate over non-ptr type |
|
var aTweet tweet |
|
count := 0 |
|
for _, item := range searchResult.Each(reflect.TypeOf(aTweet)) { |
|
count++ |
|
_, ok := item.(tweet) |
|
if !ok { |
|
t.Fatalf("expected hit to be serialized as tweet; got: %v", reflect.ValueOf(item)) |
|
} |
|
} |
|
if count == 0 { |
|
t.Errorf("expected to find some hits; got: %d", count) |
|
} |
|
|
|
// Iterate over ptr-type |
|
count = 0 |
|
var aTweetPtr *tweet |
|
for _, item := range searchResult.Each(reflect.TypeOf(aTweetPtr)) { |
|
count++ |
|
tw, ok := item.(*tweet) |
|
if !ok { |
|
t.Fatalf("expected hit to be serialized as tweet; got: %v", reflect.ValueOf(item)) |
|
} |
|
if tw == nil { |
|
t.Fatal("expected hit to not be nil") |
|
} |
|
} |
|
if count == 0 { |
|
t.Errorf("expected to find some hits; got: %d", count) |
|
} |
|
|
|
// Does not iterate when no hits are found |
|
searchResult = &SearchResult{Hits: nil} |
|
count = 0 |
|
for _, item := range searchResult.Each(reflect.TypeOf(aTweet)) { |
|
count++ |
|
_ = item |
|
} |
|
if count != 0 { |
|
t.Errorf("expected to not find any hits; got: %d", count) |
|
} |
|
searchResult = &SearchResult{Hits: &SearchHits{Hits: make([]*SearchHit, 0)}} |
|
count = 0 |
|
for _, item := range searchResult.Each(reflect.TypeOf(aTweet)) { |
|
count++ |
|
_ = item |
|
} |
|
if count != 0 { |
|
t.Errorf("expected to not find any hits; got: %d", count) |
|
} |
|
} |
|
|
|
func TestSearchResultEachNoSource(t *testing.T) { |
|
client := setupTestClientAndCreateIndexAndAddDocsNoSource(t) |
|
|
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search().Index(testIndexName).Type("tweet-nosource").Query(all).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
// Iterate over non-ptr type |
|
var aTweet tweet |
|
count := 0 |
|
for _, item := range searchResult.Each(reflect.TypeOf(aTweet)) { |
|
count++ |
|
tw, ok := item.(tweet) |
|
if !ok { |
|
t.Fatalf("expected hit to be serialized as tweet; got: %v", reflect.ValueOf(item)) |
|
} |
|
|
|
if tw.User != "" { |
|
t.Fatalf("expected no _source hit to be empty tweet; got: %v", reflect.ValueOf(item)) |
|
} |
|
} |
|
if count != 2 { |
|
t.Errorf("expected to find 2 hits; got: %d", count) |
|
} |
|
|
|
// Iterate over ptr-type |
|
count = 0 |
|
var aTweetPtr *tweet |
|
for _, item := range searchResult.Each(reflect.TypeOf(aTweetPtr)) { |
|
count++ |
|
tw, ok := item.(*tweet) |
|
if !ok { |
|
t.Fatalf("expected hit to be serialized as tweet; got: %v", reflect.ValueOf(item)) |
|
} |
|
if tw != nil { |
|
t.Fatal("expected hit to be nil") |
|
} |
|
} |
|
if count != 2 { |
|
t.Errorf("expected to find 2 hits; got: %d", count) |
|
} |
|
} |
|
|
|
func TestSearchSorting(t *testing.T) { |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
// Match all should return all documents |
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(all). |
|
Sort("created", false). |
|
Timeout("1s"). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
if len(searchResult.Hits.Hits) != 3 { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits)) |
|
} |
|
|
|
for _, hit := range searchResult.Hits.Hits { |
|
if hit.Index != testIndexName { |
|
t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index) |
|
} |
|
item := make(map[string]interface{}) |
|
err := json.Unmarshal(*hit.Source, &item) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchSortingBySorters(t *testing.T) { |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
// Match all should return all documents |
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(all). |
|
SortBy(NewFieldSort("created").Desc(), NewScoreSort()). |
|
Timeout("1s"). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
if len(searchResult.Hits.Hits) != 3 { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits)) |
|
} |
|
|
|
for _, hit := range searchResult.Hits.Hits { |
|
if hit.Index != testIndexName { |
|
t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index) |
|
} |
|
item := make(map[string]interface{}) |
|
err := json.Unmarshal(*hit.Source, &item) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchSpecificFields(t *testing.T) { |
|
// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, "", 0))) |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
tweet1 := tweet{User: "olivere", Message: "Welcome to Golang and Elasticsearch."} |
|
tweet2 := tweet{User: "olivere", Message: "Another unrelated topic."} |
|
tweet3 := tweet{User: "sandrae", Message: "Cycling is fun."} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
// Match all should return all documents |
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(all). |
|
StoredFields("message"). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
if len(searchResult.Hits.Hits) != 3 { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits)) |
|
} |
|
|
|
for _, hit := range searchResult.Hits.Hits { |
|
if hit.Index != testIndexName { |
|
t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index) |
|
} |
|
if hit.Source != nil { |
|
t.Fatalf("expected SearchResult.Hits.Hit.Source to be nil; got: %v", hit.Source) |
|
} |
|
if hit.Fields == nil { |
|
t.Fatal("expected SearchResult.Hits.Hit.Fields to be != nil") |
|
} |
|
field, found := hit.Fields["message"] |
|
if !found { |
|
t.Errorf("expected SearchResult.Hits.Hit.Fields[%s] to be found", "message") |
|
} |
|
fields, ok := field.([]interface{}) |
|
if !ok { |
|
t.Errorf("expected []interface{}; got: %v", reflect.TypeOf(fields)) |
|
} |
|
if len(fields) != 1 { |
|
t.Errorf("expected a field with 1 entry; got: %d", len(fields)) |
|
} |
|
message, ok := fields[0].(string) |
|
if !ok { |
|
t.Errorf("expected a string; got: %v", reflect.TypeOf(fields[0])) |
|
} |
|
if message == "" { |
|
t.Errorf("expected a message; got: %q", message) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchExplain(t *testing.T) { |
|
client := setupTestClientAndCreateIndex(t) |
|
// client := setupTestClientAndCreateIndex(t, SetTraceLog(log.New(os.Stdout, "", 0))) |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
// Match all should return all documents |
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(all). |
|
Explain(true). |
|
Timeout("1s"). |
|
// Pretty(true). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
if len(searchResult.Hits.Hits) != 3 { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits)) |
|
} |
|
|
|
for _, hit := range searchResult.Hits.Hits { |
|
if hit.Index != testIndexName { |
|
t.Errorf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index) |
|
} |
|
if hit.Explanation == nil { |
|
t.Fatal("expected search explanation") |
|
} |
|
if hit.Explanation.Value <= 0.0 { |
|
t.Errorf("expected explanation value to be > 0.0; got: %v", hit.Explanation.Value) |
|
} |
|
if hit.Explanation.Description == "" { |
|
t.Errorf("expected explanation description != %q; got: %q", "", hit.Explanation.Description) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchSource(t *testing.T) { |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
// Set up the request JSON manually to pass to the search service via Source() |
|
source := map[string]interface{}{ |
|
"query": map[string]interface{}{ |
|
"match_all": map[string]interface{}{}, |
|
}, |
|
} |
|
|
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Source(source). // sets the JSON request |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
} |
|
|
|
func TestSearchSourceWithString(t *testing.T) { |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Source(`{"query":{"match_all":{}}}`). // sets the JSON request |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
} |
|
|
|
func TestSearchRawString(t *testing.T) { |
|
// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, "", 0))) |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
query := RawStringQuery(`{"match_all":{}}`) |
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(query). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
} |
|
|
|
func TestSearchSearchSource(t *testing.T) { |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
// Set up the search source manually and pass it to the search service via SearchSource() |
|
ss := NewSearchSource().Query(NewMatchAllQuery()).From(0).Size(2) |
|
|
|
// One can use ss.Source() to get to the raw interface{} that will be used |
|
// as the search request JSON by the SearchService. |
|
|
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
SearchSource(ss). // sets the SearchSource |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
if len(searchResult.Hits.Hits) != 2 { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 2, len(searchResult.Hits.Hits)) |
|
} |
|
} |
|
|
|
func TestSearchInnerHitsOnHasChild(t *testing.T) { |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
// Check for valid ES version |
|
esversion, err := client.ElasticsearchVersion(DefaultURL) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if esversion < "1.5.0" { |
|
t.Skip("InnerHits feature is only available for Elasticsearch 1.5+") |
|
return |
|
} |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
comment2a := comment{User: "sandrae", Comment: "What does that even mean?"} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
comment3a := comment{User: "nico", Comment: "You bet."} |
|
comment3b := comment{User: "olivere", Comment: "It sure is."} |
|
|
|
// Add all documents |
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("t1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("t2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("comment").Id("c2a").Parent("t2").BodyJson(&comment2a).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("t3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("comment").Id("c3a").Parent("t3").BodyJson(&comment3a).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("comment").Id("c3b").Parent("t3").BodyJson(&comment3b).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
bq := NewBoolQuery() |
|
bq = bq.Must(NewMatchAllQuery()) |
|
bq = bq.Filter(NewHasChildQuery("comment", NewMatchAllQuery()). |
|
InnerHit(NewInnerHit().Name("comments"))) |
|
|
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(bq). |
|
Pretty(true). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 2 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 2, searchResult.Hits.TotalHits) |
|
} |
|
if len(searchResult.Hits.Hits) != 2 { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 2, len(searchResult.Hits.Hits)) |
|
} |
|
|
|
hit := searchResult.Hits.Hits[0] |
|
if hit.Id != "t2" { |
|
t.Fatalf("expected tweet %q; got: %q", "t2", hit.Id) |
|
} |
|
if hit.InnerHits == nil { |
|
t.Fatalf("expected inner hits; got: %v", hit.InnerHits) |
|
} |
|
if len(hit.InnerHits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits)) |
|
} |
|
innerHits, found := hit.InnerHits["comments"] |
|
if !found { |
|
t.Fatalf("expected inner hits for name %q", "comments") |
|
} |
|
if innerHits == nil || innerHits.Hits == nil { |
|
t.Fatal("expected inner hits != nil") |
|
} |
|
if len(innerHits.Hits.Hits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(innerHits.Hits.Hits)) |
|
} |
|
if innerHits.Hits.Hits[0].Id != "c2a" { |
|
t.Fatalf("expected inner hit with id %q; got: %q", "c2a", innerHits.Hits.Hits[0].Id) |
|
} |
|
|
|
hit = searchResult.Hits.Hits[1] |
|
if hit.Id != "t3" { |
|
t.Fatalf("expected tweet %q; got: %q", "t3", hit.Id) |
|
} |
|
if hit.InnerHits == nil { |
|
t.Fatalf("expected inner hits; got: %v", hit.InnerHits) |
|
} |
|
if len(hit.InnerHits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits)) |
|
} |
|
innerHits, found = hit.InnerHits["comments"] |
|
if !found { |
|
t.Fatalf("expected inner hits for name %q", "comments") |
|
} |
|
if innerHits == nil || innerHits.Hits == nil { |
|
t.Fatal("expected inner hits != nil") |
|
} |
|
if len(innerHits.Hits.Hits) != 2 { |
|
t.Fatalf("expected %d inner hits; got: %d", 2, len(innerHits.Hits.Hits)) |
|
} |
|
if innerHits.Hits.Hits[0].Id != "c3a" { |
|
t.Fatalf("expected inner hit with id %q; got: %q", "c3a", innerHits.Hits.Hits[0].Id) |
|
} |
|
if innerHits.Hits.Hits[1].Id != "c3b" { |
|
t.Fatalf("expected inner hit with id %q; got: %q", "c3b", innerHits.Hits.Hits[1].Id) |
|
} |
|
} |
|
|
|
func TestSearchInnerHitsOnHasParent(t *testing.T) { |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
// Check for valid ES version |
|
esversion, err := client.ElasticsearchVersion(DefaultURL) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if esversion < "1.5.0" { |
|
t.Skip("InnerHits feature is only available for Elasticsearch 1.5+") |
|
return |
|
} |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
comment2a := comment{User: "sandrae", Comment: "What does that even mean?"} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
comment3a := comment{User: "nico", Comment: "You bet."} |
|
comment3b := comment{User: "olivere", Comment: "It sure is."} |
|
|
|
// Add all documents |
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("t1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("t2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("comment").Id("c2a").Parent("t2").BodyJson(&comment2a).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("t3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("comment").Id("c3a").Parent("t3").BodyJson(&comment3a).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
_, err = client.Index().Index(testIndexName).Type("comment").Id("c3b").Parent("t3").BodyJson(&comment3b).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
bq := NewBoolQuery() |
|
bq = bq.Must(NewMatchAllQuery()) |
|
bq = bq.Filter(NewHasParentQuery("tweet", NewMatchAllQuery()). |
|
InnerHit(NewInnerHit().Name("tweets"))) |
|
|
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(bq). |
|
Pretty(true). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
if len(searchResult.Hits.Hits) != 3 { |
|
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", 3, len(searchResult.Hits.Hits)) |
|
} |
|
|
|
hit := searchResult.Hits.Hits[0] |
|
if hit.Id != "c2a" { |
|
t.Fatalf("expected tweet %q; got: %q", "c2a", hit.Id) |
|
} |
|
if hit.InnerHits == nil { |
|
t.Fatalf("expected inner hits; got: %v", hit.InnerHits) |
|
} |
|
if len(hit.InnerHits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits)) |
|
} |
|
innerHits, found := hit.InnerHits["tweets"] |
|
if !found { |
|
t.Fatalf("expected inner hits for name %q", "tweets") |
|
} |
|
if innerHits == nil || innerHits.Hits == nil { |
|
t.Fatal("expected inner hits != nil") |
|
} |
|
if len(innerHits.Hits.Hits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(innerHits.Hits.Hits)) |
|
} |
|
if innerHits.Hits.Hits[0].Id != "t2" { |
|
t.Fatalf("expected inner hit with id %q; got: %q", "t2", innerHits.Hits.Hits[0].Id) |
|
} |
|
|
|
hit = searchResult.Hits.Hits[1] |
|
if hit.Id != "c3a" { |
|
t.Fatalf("expected tweet %q; got: %q", "c3a", hit.Id) |
|
} |
|
if hit.InnerHits == nil { |
|
t.Fatalf("expected inner hits; got: %v", hit.InnerHits) |
|
} |
|
if len(hit.InnerHits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits)) |
|
} |
|
innerHits, found = hit.InnerHits["tweets"] |
|
if !found { |
|
t.Fatalf("expected inner hits for name %q", "tweets") |
|
} |
|
if innerHits == nil || innerHits.Hits == nil { |
|
t.Fatal("expected inner hits != nil") |
|
} |
|
if len(innerHits.Hits.Hits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(innerHits.Hits.Hits)) |
|
} |
|
if innerHits.Hits.Hits[0].Id != "t3" { |
|
t.Fatalf("expected inner hit with id %q; got: %q", "t3", innerHits.Hits.Hits[0].Id) |
|
} |
|
|
|
hit = searchResult.Hits.Hits[2] |
|
if hit.Id != "c3b" { |
|
t.Fatalf("expected tweet %q; got: %q", "c3b", hit.Id) |
|
} |
|
if hit.InnerHits == nil { |
|
t.Fatalf("expected inner hits; got: %v", hit.InnerHits) |
|
} |
|
if len(hit.InnerHits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(hit.InnerHits)) |
|
} |
|
innerHits, found = hit.InnerHits["tweets"] |
|
if !found { |
|
t.Fatalf("expected inner hits for name %q", "tweets") |
|
} |
|
if innerHits == nil || innerHits.Hits == nil { |
|
t.Fatal("expected inner hits != nil") |
|
} |
|
if len(innerHits.Hits.Hits) != 1 { |
|
t.Fatalf("expected %d inner hits; got: %d", 1, len(innerHits.Hits.Hits)) |
|
} |
|
if innerHits.Hits.Hits[0].Id != "t3" { |
|
t.Fatalf("expected inner hit with id %q; got: %q", "t3", innerHits.Hits.Hits[0].Id) |
|
} |
|
} |
|
|
|
func TestSearchBuildURL(t *testing.T) { |
|
client := setupTestClient(t) |
|
|
|
tests := []struct { |
|
Indices []string |
|
Types []string |
|
Expected string |
|
}{ |
|
{ |
|
[]string{}, |
|
[]string{}, |
|
"/_search", |
|
}, |
|
{ |
|
[]string{"index1"}, |
|
[]string{}, |
|
"/index1/_search", |
|
}, |
|
{ |
|
[]string{"index1", "index2"}, |
|
[]string{}, |
|
"/index1%2Cindex2/_search", |
|
}, |
|
{ |
|
[]string{}, |
|
[]string{"type1"}, |
|
"/_all/type1/_search", |
|
}, |
|
{ |
|
[]string{"index1"}, |
|
[]string{"type1"}, |
|
"/index1/type1/_search", |
|
}, |
|
{ |
|
[]string{"index1", "index2"}, |
|
[]string{"type1", "type2"}, |
|
"/index1%2Cindex2/type1%2Ctype2/_search", |
|
}, |
|
{ |
|
[]string{}, |
|
[]string{"type1", "type2"}, |
|
"/_all/type1%2Ctype2/_search", |
|
}, |
|
} |
|
|
|
for i, test := range tests { |
|
path, _, err := client.Search().Index(test.Indices...).Type(test.Types...).buildURL() |
|
if err != nil { |
|
t.Errorf("case #%d: %v", i+1, err) |
|
continue |
|
} |
|
if path != test.Expected { |
|
t.Errorf("case #%d: expected %q; got: %q", i+1, test.Expected, path) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchFilterPath(t *testing.T) { |
|
// client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags))) |
|
client := setupTestClientAndCreateIndexAndAddDocs(t) |
|
|
|
// Match all should return all documents |
|
all := NewMatchAllQuery() |
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Type("tweet"). |
|
Query(all). |
|
FilterPath( |
|
"took", |
|
"hits.hits._id", |
|
"hits.hits._source.user", |
|
"hits.hits._source.message", |
|
). |
|
Timeout("1s"). |
|
Pretty(true). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Fatalf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
// 0 because it was filtered out |
|
if want, got := int64(0), searchResult.Hits.TotalHits; want != got { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", want, got) |
|
} |
|
if want, got := 3, len(searchResult.Hits.Hits); want != got { |
|
t.Fatalf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, got) |
|
} |
|
|
|
for _, hit := range searchResult.Hits.Hits { |
|
if want, got := "", hit.Index; want != got { |
|
t.Fatalf("expected index %q, got %q", want, got) |
|
} |
|
item := make(map[string]interface{}) |
|
err := json.Unmarshal(*hit.Source, &item) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
// user field |
|
v, found := item["user"] |
|
if !found { |
|
t.Fatalf("expected SearchResult.Hits.Hit[%q] to be found", "user") |
|
} |
|
if v == "" { |
|
t.Fatalf("expected user field, got %v (%T)", v, v) |
|
} |
|
// No retweets field |
|
v, found = item["retweets"] |
|
if found { |
|
t.Fatalf("expected SearchResult.Hits.Hit[%q] to not be found, got %v", "retweets", v) |
|
} |
|
if v == "" { |
|
t.Fatalf("expected user field, got %v (%T)", v, v) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchAfter(t *testing.T) { |
|
// client := setupTestClientAndCreateIndexAndLog(t, SetTraceLog(log.New(os.Stdout, "", 0))) |
|
client := setupTestClientAndCreateIndex(t) |
|
|
|
tweet1 := tweet{ |
|
User: "olivere", Retweets: 108, |
|
Message: "Welcome to Golang and Elasticsearch.", |
|
Created: time.Date(2012, 12, 12, 17, 38, 34, 0, time.UTC), |
|
} |
|
tweet2 := tweet{ |
|
User: "olivere", Retweets: 0, |
|
Message: "Another unrelated topic.", |
|
Created: time.Date(2012, 10, 10, 8, 12, 03, 0, time.UTC), |
|
} |
|
tweet3 := tweet{ |
|
User: "sandrae", Retweets: 12, |
|
Message: "Cycling is fun.", |
|
Created: time.Date(2011, 11, 11, 10, 58, 12, 0, time.UTC), |
|
} |
|
|
|
// Add all documents |
|
_, err := client.Index().Index(testIndexName).Type("tweet").Id("1").BodyJson(&tweet1).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("2").BodyJson(&tweet2).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Index().Index(testIndexName).Type("tweet").Id("3").BodyJson(&tweet3).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
_, err = client.Flush().Index(testIndexName).Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Query(NewMatchAllQuery()). |
|
SearchAfter("olivere"). |
|
Sort("user", true). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if searchResult.Hits == nil { |
|
t.Errorf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if searchResult.Hits.TotalHits != 3 { |
|
t.Errorf("expected SearchResult.Hits.TotalHits = %d; got %d", 3, searchResult.Hits.TotalHits) |
|
} |
|
if want, got := 1, len(searchResult.Hits.Hits); want != got { |
|
t.Fatalf("expected len(SearchResult.Hits.Hits) = %d; got: %d", want, got) |
|
} |
|
hit := searchResult.Hits.Hits[0] |
|
if want, got := "3", hit.Id; want != got { |
|
t.Fatalf("expected tweet %q; got: %q", want, got) |
|
} |
|
} |
|
|
|
func TestSearchResultWithFieldCollapsing(t *testing.T) { |
|
client := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, "", 0))) |
|
|
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Type("tweet"). |
|
Query(NewMatchAllQuery()). |
|
Collapse(NewCollapseBuilder("user")). |
|
Pretty(true). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
if searchResult.Hits == nil { |
|
t.Fatalf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if got := searchResult.Hits.TotalHits; got == 0 { |
|
t.Fatalf("expected SearchResult.Hits.TotalHits > 0; got %d", got) |
|
} |
|
|
|
for _, hit := range searchResult.Hits.Hits { |
|
if hit.Index != testIndexName { |
|
t.Fatalf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index) |
|
} |
|
item := make(map[string]interface{}) |
|
err := json.Unmarshal(*hit.Source, &item) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if len(hit.Fields) == 0 { |
|
t.Fatal("expected fields in SearchResult") |
|
} |
|
usersVal, ok := hit.Fields["user"] |
|
if !ok { |
|
t.Fatalf("expected %q field in fields of SearchResult", "user") |
|
} |
|
users, ok := usersVal.([]interface{}) |
|
if !ok { |
|
t.Fatalf("expected slice of strings in field of SearchResult, got %T", usersVal) |
|
} |
|
if len(users) != 1 { |
|
t.Fatalf("expected 1 entry in users slice, got %d", len(users)) |
|
} |
|
} |
|
} |
|
|
|
func TestSearchResultWithFieldCollapsingAndInnerHits(t *testing.T) { |
|
client := setupTestClientAndCreateIndexAndAddDocs(t) // , SetTraceLog(log.New(os.Stdout, "", 0))) |
|
|
|
searchResult, err := client.Search(). |
|
Index(testIndexName). |
|
Type("tweet"). |
|
Query(NewMatchAllQuery()). |
|
Collapse( |
|
NewCollapseBuilder("user"). |
|
InnerHit( |
|
NewInnerHit().Name("last_tweets").Size(5).Sort("created", true), |
|
). |
|
MaxConcurrentGroupRequests(4)). |
|
Pretty(true). |
|
Do(context.TODO()) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
|
|
if searchResult.Hits == nil { |
|
t.Fatalf("expected SearchResult.Hits != nil; got nil") |
|
} |
|
if got := searchResult.Hits.TotalHits; got == 0 { |
|
t.Fatalf("expected SearchResult.Hits.TotalHits > 0; got %d", got) |
|
} |
|
|
|
for _, hit := range searchResult.Hits.Hits { |
|
if hit.Index != testIndexName { |
|
t.Fatalf("expected SearchResult.Hits.Hit.Index = %q; got %q", testIndexName, hit.Index) |
|
} |
|
item := make(map[string]interface{}) |
|
err := json.Unmarshal(*hit.Source, &item) |
|
if err != nil { |
|
t.Fatal(err) |
|
} |
|
if len(hit.Fields) == 0 { |
|
t.Fatal("expected fields in SearchResult") |
|
} |
|
usersVal, ok := hit.Fields["user"] |
|
if !ok { |
|
t.Fatalf("expected %q field in fields of SearchResult", "user") |
|
} |
|
users, ok := usersVal.([]interface{}) |
|
if !ok { |
|
t.Fatalf("expected slice of strings in field of SearchResult, got %T", usersVal) |
|
} |
|
if len(users) != 1 { |
|
t.Fatalf("expected 1 entry in users slice, got %d", len(users)) |
|
} |
|
lastTweets, ok := hit.InnerHits["last_tweets"] |
|
if !ok { |
|
t.Fatalf("expected inner_hits named %q in SearchResult", "last_tweets") |
|
} |
|
if lastTweets == nil { |
|
t.Fatal("expected inner_hits in SearchResult") |
|
} |
|
} |
|
}
|
|
|