123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453 |
- // 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 (
- "fmt"
- )
- // SearchSource enables users to build the search source.
- // It resembles the SearchSourceBuilder in Elasticsearch.
- type SearchSource struct {
- query Query
- postFilter Filter
- from int
- size int
- explain *bool
- version *bool
- sorts []SortInfo
- sorters []Sorter
- trackScores bool
- minScore *float64
- timeout string
- fieldNames []string
- fieldDataFields []string
- scriptFields []*ScriptField
- partialFields []*PartialField
- fetchSourceContext *FetchSourceContext
- facets map[string]Facet
- aggregations map[string]Aggregation
- highlight *Highlight
- globalSuggestText string
- suggesters []Suggester
- rescores []*Rescore
- defaultRescoreWindowSize *int
- indexBoosts map[string]float64
- stats []string
- }
- func NewSearchSource() *SearchSource {
- return &SearchSource{
- from: -1,
- size: -1,
- trackScores: false,
- sorts: make([]SortInfo, 0),
- sorters: make([]Sorter, 0),
- fieldDataFields: make([]string, 0),
- scriptFields: make([]*ScriptField, 0),
- partialFields: make([]*PartialField, 0),
- facets: make(map[string]Facet),
- aggregations: make(map[string]Aggregation),
- rescores: make([]*Rescore, 0),
- indexBoosts: make(map[string]float64),
- stats: make([]string, 0),
- }
- }
- // Query sets the query to use with this search source.
- func (s *SearchSource) Query(query Query) *SearchSource {
- s.query = query
- return s
- }
- // PostFilter is executed as the last filter. It only affects the
- // search hits but not facets.
- func (s *SearchSource) PostFilter(postFilter Filter) *SearchSource {
- s.postFilter = postFilter
- return s
- }
- func (s *SearchSource) From(from int) *SearchSource {
- s.from = from
- return s
- }
- func (s *SearchSource) Size(size int) *SearchSource {
- s.size = size
- return s
- }
- func (s *SearchSource) MinScore(minScore float64) *SearchSource {
- s.minScore = &minScore
- return s
- }
- func (s *SearchSource) Explain(explain bool) *SearchSource {
- s.explain = &explain
- return s
- }
- func (s *SearchSource) Version(version bool) *SearchSource {
- s.version = &version
- return s
- }
- func (s *SearchSource) Timeout(timeout string) *SearchSource {
- s.timeout = timeout
- return s
- }
- func (s *SearchSource) TimeoutInMillis(timeoutInMillis int) *SearchSource {
- s.timeout = fmt.Sprintf("%dms", timeoutInMillis)
- return s
- }
- func (s *SearchSource) Sort(field string, ascending bool) *SearchSource {
- s.sorts = append(s.sorts, SortInfo{Field: field, Ascending: ascending})
- return s
- }
- func (s *SearchSource) SortWithInfo(info SortInfo) *SearchSource {
- s.sorts = append(s.sorts, info)
- return s
- }
- func (s *SearchSource) SortBy(sorter ...Sorter) *SearchSource {
- s.sorters = append(s.sorters, sorter...)
- return s
- }
- func (s *SearchSource) TrackScores(trackScores bool) *SearchSource {
- s.trackScores = trackScores
- return s
- }
- func (s *SearchSource) Facet(name string, facet Facet) *SearchSource {
- s.facets[name] = facet
- return s
- }
- func (s *SearchSource) Aggregation(name string, aggregation Aggregation) *SearchSource {
- s.aggregations[name] = aggregation
- return s
- }
- func (s *SearchSource) DefaultRescoreWindowSize(defaultRescoreWindowSize int) *SearchSource {
- s.defaultRescoreWindowSize = &defaultRescoreWindowSize
- return s
- }
- func (s *SearchSource) Highlight(highlight *Highlight) *SearchSource {
- s.highlight = highlight
- return s
- }
- func (s *SearchSource) Highlighter() *Highlight {
- if s.highlight == nil {
- s.highlight = NewHighlight()
- }
- return s.highlight
- }
- func (s *SearchSource) GlobalSuggestText(text string) *SearchSource {
- s.globalSuggestText = text
- return s
- }
- func (s *SearchSource) Suggester(suggester Suggester) *SearchSource {
- s.suggesters = append(s.suggesters, suggester)
- return s
- }
- func (s *SearchSource) AddRescore(rescore *Rescore) *SearchSource {
- s.rescores = append(s.rescores, rescore)
- return s
- }
- func (s *SearchSource) ClearRescores() *SearchSource {
- s.rescores = make([]*Rescore, 0)
- return s
- }
- func (s *SearchSource) FetchSource(fetchSource bool) *SearchSource {
- if s.fetchSourceContext == nil {
- s.fetchSourceContext = NewFetchSourceContext(fetchSource)
- } else {
- s.fetchSourceContext.SetFetchSource(fetchSource)
- }
- return s
- }
- func (s *SearchSource) FetchSourceContext(fetchSourceContext *FetchSourceContext) *SearchSource {
- s.fetchSourceContext = fetchSourceContext
- return s
- }
- func (s *SearchSource) Fields(fieldNames ...string) *SearchSource {
- if s.fieldNames == nil {
- s.fieldNames = make([]string, 0)
- }
- s.fieldNames = append(s.fieldNames, fieldNames...)
- return s
- }
- func (s *SearchSource) Field(fieldName string) *SearchSource {
- if s.fieldNames == nil {
- s.fieldNames = make([]string, 0)
- }
- s.fieldNames = append(s.fieldNames, fieldName)
- return s
- }
- func (s *SearchSource) NoFields() *SearchSource {
- s.fieldNames = make([]string, 0)
- return s
- }
- func (s *SearchSource) FieldDataFields(fieldDataFields ...string) *SearchSource {
- s.fieldDataFields = append(s.fieldDataFields, fieldDataFields...)
- return s
- }
- func (s *SearchSource) FieldDataField(fieldDataField string) *SearchSource {
- s.fieldDataFields = append(s.fieldDataFields, fieldDataField)
- return s
- }
- func (s *SearchSource) ScriptFields(scriptFields ...*ScriptField) *SearchSource {
- s.scriptFields = append(s.scriptFields, scriptFields...)
- return s
- }
- func (s *SearchSource) ScriptField(scriptField *ScriptField) *SearchSource {
- s.scriptFields = append(s.scriptFields, scriptField)
- return s
- }
- func (s *SearchSource) PartialFields(partialFields ...*PartialField) *SearchSource {
- s.partialFields = append(s.partialFields, partialFields...)
- return s
- }
- func (s *SearchSource) PartialField(partialField *PartialField) *SearchSource {
- s.partialFields = append(s.partialFields, partialField)
- return s
- }
- func (s *SearchSource) IndexBoost(index string, boost float64) *SearchSource {
- s.indexBoosts[index] = boost
- return s
- }
- func (s *SearchSource) Stats(statsGroup ...string) *SearchSource {
- s.stats = append(s.stats, statsGroup...)
- return s
- }
- func (s *SearchSource) Source() interface{} {
- source := make(map[string]interface{})
- if s.from != -1 {
- source["from"] = s.from
- }
- if s.size != -1 {
- source["size"] = s.size
- }
- if s.timeout != "" {
- source["timeout"] = s.timeout
- }
- if s.query != nil {
- source["query"] = s.query.Source()
- }
- if s.postFilter != nil {
- source["post_filter"] = s.postFilter.Source()
- }
- if s.minScore != nil {
- source["min_score"] = *s.minScore
- }
- if s.version != nil {
- source["version"] = *s.version
- }
- if s.explain != nil {
- source["explain"] = *s.explain
- }
- if s.fetchSourceContext != nil {
- source["_source"] = s.fetchSourceContext.Source()
- }
- if s.fieldNames != nil {
- switch len(s.fieldNames) {
- case 1:
- source["fields"] = s.fieldNames[0]
- default:
- source["fields"] = s.fieldNames
- }
- }
- if len(s.fieldDataFields) > 0 {
- source["fielddata_fields"] = s.fieldDataFields
- }
- if len(s.partialFields) > 0 {
- pfmap := make(map[string]interface{})
- for _, partialField := range s.partialFields {
- pfmap[partialField.Name] = partialField.Source()
- }
- source["partial_fields"] = pfmap
- }
- if len(s.scriptFields) > 0 {
- sfmap := make(map[string]interface{})
- for _, scriptField := range s.scriptFields {
- sfmap[scriptField.FieldName] = scriptField.Source()
- }
- source["script_fields"] = sfmap
- }
- if len(s.sorters) > 0 {
- sortarr := make([]interface{}, 0)
- for _, sorter := range s.sorters {
- sortarr = append(sortarr, sorter.Source())
- }
- source["sort"] = sortarr
- } else if len(s.sorts) > 0 {
- sortarr := make([]interface{}, 0)
- for _, sort := range s.sorts {
- sortarr = append(sortarr, sort.Source())
- }
- source["sort"] = sortarr
- }
- if s.trackScores {
- source["track_scores"] = s.trackScores
- }
- if len(s.indexBoosts) > 0 {
- source["indices_boost"] = s.indexBoosts
- }
- if len(s.facets) > 0 {
- facetsMap := make(map[string]interface{})
- for field, facet := range s.facets {
- facetsMap[field] = facet.Source()
- }
- source["facets"] = facetsMap
- }
- if len(s.aggregations) > 0 {
- aggsMap := make(map[string]interface{})
- for name, aggregate := range s.aggregations {
- aggsMap[name] = aggregate.Source()
- }
- source["aggregations"] = aggsMap
- }
- if s.highlight != nil {
- source["highlight"] = s.highlight.Source()
- }
- if len(s.suggesters) > 0 {
- suggesters := make(map[string]interface{})
- for _, s := range s.suggesters {
- suggesters[s.Name()] = s.Source(false)
- }
- if s.globalSuggestText != "" {
- suggesters["text"] = s.globalSuggestText
- }
- source["suggest"] = suggesters
- }
- if len(s.rescores) > 0 {
- // Strip empty rescores from request
- rescores := make([]*Rescore, 0)
- for _, r := range s.rescores {
- if !r.IsEmpty() {
- rescores = append(rescores, r)
- }
- }
- if len(rescores) == 1 {
- rescores[0].defaultRescoreWindowSize = s.defaultRescoreWindowSize
- source["rescore"] = rescores[0].Source()
- } else {
- slice := make([]interface{}, 0)
- for _, r := range rescores {
- r.defaultRescoreWindowSize = s.defaultRescoreWindowSize
- slice = append(slice, r.Source())
- }
- source["rescore"] = slice
- }
- }
- if len(s.stats) > 0 {
- source["stats"] = s.stats
- }
- return source
- }
- // -- Script Field --
- type ScriptField struct {
- FieldName string
- script string
- lang string
- params map[string]interface{}
- }
- func NewScriptField(fieldName, script, lang string, params map[string]interface{}) *ScriptField {
- return &ScriptField{fieldName, script, lang, params}
- }
- func (f *ScriptField) Source() interface{} {
- source := make(map[string]interface{})
- source["script"] = f.script
- if f.lang != "" {
- source["lang"] = f.lang
- }
- if f.params != nil && len(f.params) > 0 {
- source["params"] = f.params
- }
- return source
- }
- // -- Partial Field --
- type PartialField struct {
- Name string
- includes []string
- excludes []string
- }
- func NewPartialField(name string, includes, excludes []string) *PartialField {
- return &PartialField{name, includes, excludes}
- }
- func (f *PartialField) Source() interface{} {
- source := make(map[string]interface{})
- if f.includes != nil {
- switch len(f.includes) {
- case 0:
- case 1:
- source["include"] = f.includes[0]
- default:
- source["include"] = f.includes
- }
- }
- if f.excludes != nil {
- switch len(f.excludes) {
- case 0:
- case 1:
- source["exclude"] = f.excludes[0]
- default:
- source["exclude"] = f.excludes
- }
- }
- return source
- }
|