1371 lines
38 KiB
Go
1371 lines
38 KiB
Go
// 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")
|
|
}
|
|
}
|
|
}
|