cadvisor/vendor/gopkg.in/olivere/elastic.v2/search.go
Vishnu kannan de4af1288b moving deps to vendor subdirectory
Signed-off-by: Vishnu kannan <vishnuk@google.com>
2016-07-11 12:19:43 -07:00

540 lines
19 KiB
Go

// Copyright 2012-2015 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"
"fmt"
"net/url"
"reflect"
"strings"
"gopkg.in/olivere/elastic.v2/uritemplates"
)
// Search for documents in Elasticsearch.
type SearchService struct {
client *Client
searchSource *SearchSource
source interface{}
pretty bool
searchType string
indices []string
queryHint string
routing string
preference string
types []string
}
// NewSearchService creates a new service for searching in Elasticsearch.
// You typically do not create the service yourself manually, but access
// it via client.Search().
func NewSearchService(client *Client) *SearchService {
builder := &SearchService{
client: client,
searchSource: NewSearchSource(),
}
return builder
}
// SearchSource sets the search source builder to use with this service.
func (s *SearchService) SearchSource(searchSource *SearchSource) *SearchService {
s.searchSource = searchSource
if s.searchSource == nil {
s.searchSource = NewSearchSource()
}
return s
}
// Source allows the user to set the request body manually without using
// any of the structs and interfaces in Elastic.
func (s *SearchService) Source(source interface{}) *SearchService {
s.source = source
return s
}
// Index sets the name of the index to use for search.
func (s *SearchService) Index(index string) *SearchService {
if s.indices == nil {
s.indices = make([]string, 0)
}
s.indices = append(s.indices, index)
return s
}
// Indices sets the names of the indices to use for search.
func (s *SearchService) Indices(indices ...string) *SearchService {
if s.indices == nil {
s.indices = make([]string, 0)
}
s.indices = append(s.indices, indices...)
return s
}
// Type restricts the search for the given type.
func (s *SearchService) Type(typ string) *SearchService {
if s.types == nil {
s.types = []string{typ}
} else {
s.types = append(s.types, typ)
}
return s
}
// Types allows to restrict the search to a list of types.
func (s *SearchService) Types(types ...string) *SearchService {
if s.types == nil {
s.types = make([]string, 0)
}
s.types = append(s.types, types...)
return s
}
// Pretty enables the caller to indent the JSON output.
func (s *SearchService) Pretty(pretty bool) *SearchService {
s.pretty = pretty
return s
}
// Timeout sets the timeout to use, e.g. "1s" or "1000ms".
func (s *SearchService) Timeout(timeout string) *SearchService {
s.searchSource = s.searchSource.Timeout(timeout)
return s
}
// TimeoutInMillis sets the timeout in milliseconds.
func (s *SearchService) TimeoutInMillis(timeoutInMillis int) *SearchService {
s.searchSource = s.searchSource.TimeoutInMillis(timeoutInMillis)
return s
}
// 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 http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-search-type.html#search-request-search-type
// for details.
func (s *SearchService) SearchType(searchType string) *SearchService {
s.searchType = searchType
return s
}
// Routing allows for (a comma-separated) list of specific routing values.
func (s *SearchService) Routing(routings ...string) *SearchService {
s.routing = strings.Join(routings, ",")
return s
}
// Preference specifies the node or shard the operation should be
// performed on (default: "random").
func (s *SearchService) Preference(preference string) *SearchService {
s.preference = preference
return s
}
func (s *SearchService) QueryHint(queryHint string) *SearchService {
s.queryHint = queryHint
return s
}
// Query sets the query to perform, e.g. MatchAllQuery.
func (s *SearchService) Query(query Query) *SearchService {
s.searchSource = s.searchSource.Query(query)
return s
}
// PostFilter is executed as the last filter. It only affects the
// search hits but not facets. See
// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-post-filter.html
// for details.
func (s *SearchService) PostFilter(postFilter Filter) *SearchService {
s.searchSource = s.searchSource.PostFilter(postFilter)
return s
}
// FetchSource indicates whether the response should contain the stored
// _source for every hit.
func (s *SearchService) FetchSource(fetchSource bool) *SearchService {
s.searchSource = s.searchSource.FetchSource(fetchSource)
return s
}
// FetchSourceContext indicates how the _source should be fetched.
func (s *SearchService) FetchSourceContext(fetchSourceContext *FetchSourceContext) *SearchService {
s.searchSource = s.searchSource.FetchSourceContext(fetchSourceContext)
return s
}
// Highlight sets the highlighting. See
// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html
// for details.
func (s *SearchService) Highlight(highlight *Highlight) *SearchService {
s.searchSource = s.searchSource.Highlight(highlight)
return s
}
// GlobalSuggestText sets the global text for suggesters. See
// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html#global-suggest
// for details.
func (s *SearchService) GlobalSuggestText(globalText string) *SearchService {
s.searchSource = s.searchSource.GlobalSuggestText(globalText)
return s
}
// Suggester sets the suggester. See
// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html
// for details.
func (s *SearchService) Suggester(suggester Suggester) *SearchService {
s.searchSource = s.searchSource.Suggester(suggester)
return s
}
// Facet adds a facet to the search. See
// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.html
// to get an overview of Elasticsearch facets.
func (s *SearchService) Facet(name string, facet Facet) *SearchService {
s.searchSource = s.searchSource.Facet(name, facet)
return s
}
// Aggregation adds an aggregation to the search. See
// http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations.html
// for an overview of aggregations in Elasticsearch.
func (s *SearchService) Aggregation(name string, aggregation Aggregation) *SearchService {
s.searchSource = s.searchSource.Aggregation(name, aggregation)
return s
}
// MinScore excludes documents which have a score less than the minimum
// specified here. See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-min-score.html.
func (s *SearchService) MinScore(minScore float64) *SearchService {
s.searchSource = s.searchSource.MinScore(minScore)
return s
}
// From defines the offset from the first result you want to fetch.
// Use it in combination with Size to paginate through results.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-from-size.html
// for details.
func (s *SearchService) From(from int) *SearchService {
s.searchSource = s.searchSource.From(from)
return s
}
// Size defines the maximum number of hits to be returned.
// Use it in combination with From to paginate through results.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-from-size.html
// for details.
func (s *SearchService) Size(size int) *SearchService {
s.searchSource = s.searchSource.Size(size)
return s
}
// Explain can be enabled to provide an explanation for each hit and how its
// score was computed.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-explain.html
// for details.
func (s *SearchService) Explain(explain bool) *SearchService {
s.searchSource = s.searchSource.Explain(explain)
return s
}
// Version can be set to true to return a version for each search hit.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-version.html.
func (s *SearchService) Version(version bool) *SearchService {
s.searchSource = s.searchSource.Version(version)
return s
}
// Sort the results by the given field, in the given order.
// Use the alternative SortWithInfo to use a struct to define the sorting.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html
// for detailed documentation of sorting.
func (s *SearchService) Sort(field string, ascending bool) *SearchService {
s.searchSource = s.searchSource.Sort(field, ascending)
return s
}
// SortWithInfo defines how to sort results.
// Use the Sort func for a shortcut.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html
// for detailed documentation of sorting.
func (s *SearchService) SortWithInfo(info SortInfo) *SearchService {
s.searchSource = s.searchSource.SortWithInfo(info)
return s
}
// SortBy defines how to sort results.
// Use the Sort func for a shortcut.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-sort.html
// for detailed documentation of sorting.
func (s *SearchService) SortBy(sorter ...Sorter) *SearchService {
s.searchSource = s.searchSource.SortBy(sorter...)
return s
}
// Fields tells Elasticsearch to only load specific fields from a search hit.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-fields.html.
func (s *SearchService) Fields(fields ...string) *SearchService {
s.searchSource = s.searchSource.Fields(fields...)
return s
}
// Do executes the search and returns a SearchResult.
func (s *SearchService) Do() (*SearchResult, error) {
// Build url
path := "/"
// Indices part
indexPart := make([]string, 0)
for _, index := range s.indices {
index, err := uritemplates.Expand("{index}", map[string]string{
"index": index,
})
if err != nil {
return nil, err
}
indexPart = append(indexPart, index)
}
path += strings.Join(indexPart, ",")
// Types part
if len(s.types) > 0 {
typesPart := make([]string, 0)
for _, typ := range s.types {
typ, err := uritemplates.Expand("{type}", map[string]string{
"type": typ,
})
if err != nil {
return nil, err
}
typesPart = append(typesPart, typ)
}
path += "/"
path += strings.Join(typesPart, ",")
}
// Search
path += "/_search"
// Parameters
params := make(url.Values)
if s.pretty {
params.Set("pretty", fmt.Sprintf("%v", s.pretty))
}
if s.searchType != "" {
params.Set("search_type", s.searchType)
}
if s.routing != "" {
params.Set("routing", s.routing)
}
// Perform request
var body interface{}
if s.source != nil {
body = s.source
} else {
body = s.searchSource.Source()
}
res, err := s.client.PerformRequest("POST", path, params, body)
if err != nil {
return nil, err
}
// Return search results
ret := new(SearchResult)
if err := json.Unmarshal(res.Body, ret); err != nil {
return nil, err
}
return ret, nil
}
// SearchResult is the result of a search in Elasticsearch.
type SearchResult struct {
TookInMillis int64 `json:"took"` // search time in milliseconds
ScrollId string `json:"_scroll_id"` // only used with Scroll and Scan operations
Hits *SearchHits `json:"hits"` // the actual search hits
Suggest SearchSuggest `json:"suggest"` // results from suggesters
Facets SearchFacets `json:"facets"` // results from facets
Aggregations Aggregations `json:"aggregations"` // results from aggregations
TimedOut bool `json:"timed_out"` // true if the search timed out
Error string `json:"error,omitempty"` // used in MultiSearch only
}
// TotalHits is a convenience function to return the number of hits for
// a search result.
func (r *SearchResult) TotalHits() int64 {
if r.Hits != nil {
return r.Hits.TotalHits
}
return 0
}
// Each is a utility function to iterate over all hits. It saves you from
// checking for nil values. Notice that Each will ignore errors in
// serializing JSON.
func (r *SearchResult) Each(typ reflect.Type) []interface{} {
if r.Hits == nil || r.Hits.Hits == nil || len(r.Hits.Hits) == 0 {
return nil
}
slice := make([]interface{}, 0)
for _, hit := range r.Hits.Hits {
v := reflect.New(typ).Elem()
if err := json.Unmarshal(*hit.Source, v.Addr().Interface()); err == nil {
slice = append(slice, v.Interface())
}
}
return slice
}
// SearchHits specifies the list of search hits.
type SearchHits struct {
TotalHits int64 `json:"total"` // total number of hits found
MaxScore *float64 `json:"max_score"` // maximum score of all hits
Hits []*SearchHit `json:"hits"` // the actual hits returned
}
// SearchHit is a single hit.
type SearchHit struct {
Score *float64 `json:"_score"` // computed score
Index string `json:"_index"` // index name
Id string `json:"_id"` // external or internal
Type string `json:"_type"` // type
Version *int64 `json:"_version"` // version number, when Version is set to true in SearchService
Sort []interface{} `json:"sort"` // sort information
Highlight SearchHitHighlight `json:"highlight"` // highlighter information
Source *json.RawMessage `json:"_source"` // stored document source
Fields map[string]interface{} `json:"fields"` // returned fields
Explanation *SearchExplanation `json:"_explanation"` // explains how the score was computed
MatchedQueries []string `json:"matched_queries"` // matched queries
InnerHits map[string]*SearchHitInnerHits `json:"inner_hits"` // inner hits with ES >= 1.5.0
// Shard
// HighlightFields
// SortValues
// MatchedFilters
}
type SearchHitInnerHits struct {
Hits *SearchHits `json:"hits"`
}
// SearchExplanation explains how the score for a hit was computed.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/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:"
Details []SearchExplanation `json:"details,omitempty"` // recursive details
}
// Suggest
// SearchSuggest is a map of suggestions.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html.
type SearchSuggest map[string][]SearchSuggestion
// SearchSuggestion is a single search suggestion.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html.
type SearchSuggestion struct {
Text string `json:"text"`
Offset int `json:"offset"`
Length int `json:"length"`
Options []SearchSuggestionOption `json:"options"`
}
// SearchSuggestionOption is an option of a SearchSuggestion.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-suggesters.html.
type SearchSuggestionOption struct {
Text string `json:"text"`
Score float32 `json:"score"`
Freq int `json:"freq"`
Payload interface{} `json:"payload"`
}
// Facets
// SearchFacets is a map of facets.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.html.
type SearchFacets map[string]*SearchFacet
// SearchFacet is a single facet.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.html.
type SearchFacet struct {
Type string `json:"_type"`
Missing int `json:"missing"`
Total int `json:"total"`
Other int `json:"other"`
Terms []searchFacetTerm `json:"terms"`
Ranges []searchFacetRange `json:"ranges"`
Entries []searchFacetEntry `json:"entries"`
}
// searchFacetTerm is the result of a terms/terms_stats facet.
// See https://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-facets-terms-facet.html
// and https://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-facets-terms-stats-facet.html.
type searchFacetTerm struct {
Term interface{} `json:"term"`
Count int `json:"count"`
// The following fields are returned for terms_stats facets.
// See https://www.elastic.co/guide/en/elasticsearch/reference/1.7/search-facets-terms-stats-facet.html.
TotalCount int `json:"total_count"`
Min float64 `json:"min"`
Max float64 `json:"max"`
Total float64 `json:"total"`
Mean float64 `json:"mean"`
}
// searchFacetRange is the result of a range facet.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets-range-facet.html.
type searchFacetRange struct {
From *float64 `json:"from"`
FromStr *string `json:"from_str"`
To *float64 `json:"to"`
ToStr *string `json:"to_str"`
Count int `json:"count"`
Min *float64 `json:"min"`
Max *float64 `json:"max"`
TotalCount int `json:"total_count"`
Total *float64 `json:"total"`
Mean *float64 `json:"mean"`
}
// searchFacetEntry is a general facet entry.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-facets.html
type searchFacetEntry struct {
// Key for this facet, e.g. in histograms
Key interface{} `json:"key"`
// Date histograms contain the number of milliseconds as date:
// If e.Time = 1293840000000, then: Time.at(1293840000000/1000) => 2011-01-01
Time int64 `json:"time"`
// Number of hits for this facet
Count int `json:"count"`
// Min is either a string like "Infinity" or a float64.
// This is returned with some DateHistogram facets.
Min interface{} `json:"min,omitempty"`
// Max is either a string like "-Infinity" or a float64
// This is returned with some DateHistogram facets.
Max interface{} `json:"max,omitempty"`
// Total is the sum of all entries on the recorded Time
// This is returned with some DateHistogram facets.
Total float64 `json:"total,omitempty"`
// TotalCount is the number of entries for Total
// This is returned with some DateHistogram facets.
TotalCount int `json:"total_count,omitempty"`
// Mean is the mean value
// This is returned with some DateHistogram facets.
Mean float64 `json:"mean,omitempty"`
}
// Aggregations (see search_aggs.go)
// Highlighting
// SearchHitHighlight is the highlight information of a search hit.
// See http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-highlighting.html
// for a general discussion of highlighting.
type SearchHitHighlight map[string][]string