Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to provide API for executing Search Template - Closes #977 #1391

Open
wants to merge 2 commits into
base: release-branch.v7
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions search.go
Expand Up @@ -31,6 +31,8 @@ type SearchService struct {
searchType string // search_type
index []string
typ []string
storedScript *Script
template bool // template search
routing string // routing
preference string // preference
requestCache *bool // request_cache
Expand Down Expand Up @@ -204,6 +206,13 @@ func (s *SearchService) Query(query Query) *SearchService {
return s
}

// Execute a search template based on a stored script.
func (s *SearchService) Template(storedScript *Script) *SearchService {
s.template = true
s.searchSource.StoredScript(storedScript)
return s
}

// PostFilter will be executed after the query has been executed and
// only affects the search hits, not the aggregations.
// This filter is always executed as the last filtering mechanism.
Expand Down Expand Up @@ -505,6 +514,10 @@ func (s *SearchService) buildURL() (string, url.Values, error) {
"index": strings.Join(s.index, ","),
"type": strings.Join(s.typ, ","),
})
} else if len(s.index) > 0 && s.template {
path, err = uritemplates.Expand("/{index}/_search/template", map[string]string{
"index": strings.Join(s.index, ","),
})
} else if len(s.index) > 0 {
path, err = uritemplates.Expand("/{index}/_search", map[string]string{
"index": strings.Join(s.index, ","),
Expand Down
10 changes: 10 additions & 0 deletions search_source.go
Expand Up @@ -41,6 +41,7 @@ type SearchSource struct {
innerHits map[string]*InnerHit
collapse *CollapseBuilder // collapse
profile bool // profile
storedScript *Script // stored script
// TODO extBuilders []SearchExtBuilder // ext
}

Expand Down Expand Up @@ -324,6 +325,11 @@ func (s *SearchSource) DocvalueFieldsWithFormat(docvalueFields ...DocvalueField)
return s
}

func (s *SearchSource) StoredScript(storedScript *Script) *SearchSource {
s.storedScript = storedScript
return s
}

// ScriptField adds a single script field with the provided script.
func (s *SearchSource) ScriptField(scriptField *ScriptField) *SearchSource {
s.scriptFields = append(s.scriptFields, scriptField)
Expand Down Expand Up @@ -597,6 +603,10 @@ func (s *SearchSource) Source() (interface{}, error) {
source["inner_hits"] = m
}

if s.storedScript != nil {
return s.storedScript.Source()
}

return source, nil
}

Expand Down
19 changes: 19 additions & 0 deletions search_source_test.go
Expand Up @@ -316,3 +316,22 @@ func TestSearchSourceSeqNoAndPrimaryTerm(t *testing.T) {
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
}
}

func TestSearchSourceStoredScript(t *testing.T) {
storedScript := NewScriptStored("complex_query").Param("query_string", "token")
builder := NewSearchSource().StoredScript(storedScript)
src, err := builder.Source()
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 := `{"id":"complex_query","params":{"query_string":"token"}}`
if got != expected {
t.Errorf("expected\n%s\n,got:\n%s", expected, got)
}

}
61 changes: 61 additions & 0 deletions search_test.go
Expand Up @@ -1439,6 +1439,67 @@ func TestSearchScriptQuery(t *testing.T) {
}
}

func TestSearchStoredScript(t *testing.T) {
client := setupTestClientAndCreateIndexAndAddDocs(t) //, SetTraceLog(log.New(os.Stdout, "", 0)))

scriptId := "test_script"

// Put script to use for template search
putScriptResponse, err := client.PutScript().
Id(scriptId).
BodyString(`{
"script": {
"lang": "mustache",
"source": {
"query": {
"match": {
"{{field}}": "{{query_string}}"
}
}
}
}
}`).
Pretty(true).
Do(context.TODO())
if err != nil {
t.Fatal(err)
}
if !putScriptResponse.Acknowledged {
t.Error("put script not acknowledged")
}

// Create stored script for template search
storedScript := NewScriptStored(scriptId).Param("field", "message").Param("query_string", "Golang")

// Execute search template
searchResult, err := client.Search().
Index(testIndexName).
Template(storedScript).
Pretty(true).
Do(context.TODO())
if err != nil {
t.Fatal(err)
}
if searchResult.Hits == nil {
t.Errorf("expected SearchResult.Hits != nil; got nil")
}
if want, have := int64(1), searchResult.TotalHits(); want != have {
t.Errorf("expected SearchResult.TotalHits() = %d; got %d", want, have)
}
if want, have := 1, len(searchResult.Hits.Hits); want != have {
t.Errorf("expected len(SearchResult.Hits.Hits) = %d; got %d", want, have)
}

// Remove stored script
deleteScriptResponse, err := client.DeleteScript().Id(scriptId).Do(context.TODO())
if err != nil {
t.Fatal(err)
}
if !deleteScriptResponse.Acknowledged {
t.Error("delete script not acknowledged")
}
}

func TestSearchWithDocvalueFields(t *testing.T) {
// client := setupTestClientAndCreateIndexAndAddDocs(t, SetTraceLog(log.New(os.Stdout, "", log.LstdFlags)))
client := setupTestClientAndCreateIndexAndAddDocs(t)
Expand Down