// 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 // Highlight allows highlighting search results on one or more fields. // For details, see: // https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-highlighting.html type Highlight struct { fields []*HighlighterField tagsSchema *string highlightFilter *bool fragmentSize *int numOfFragments *int preTags []string postTags []string order *string encoder *string requireFieldMatch *bool maxAnalyzedOffset *int boundaryMaxScan *int boundaryChars *string boundaryScannerType *string boundaryScannerLocale *string highlighterType *string fragmenter *string highlightQuery Query noMatchSize *int phraseLimit *int options map[string]interface{} forceSource *bool useExplicitFieldOrder bool } func NewHighlight() *Highlight { hl := &Highlight{ options: make(map[string]interface{}), } return hl } func (hl *Highlight) Fields(fields ...*HighlighterField) *Highlight { hl.fields = append(hl.fields, fields...) return hl } func (hl *Highlight) Field(name string) *Highlight { field := NewHighlighterField(name) hl.fields = append(hl.fields, field) return hl } func (hl *Highlight) TagsSchema(schemaName string) *Highlight { hl.tagsSchema = &schemaName return hl } func (hl *Highlight) HighlightFilter(highlightFilter bool) *Highlight { hl.highlightFilter = &highlightFilter return hl } func (hl *Highlight) FragmentSize(fragmentSize int) *Highlight { hl.fragmentSize = &fragmentSize return hl } func (hl *Highlight) NumOfFragments(numOfFragments int) *Highlight { hl.numOfFragments = &numOfFragments return hl } func (hl *Highlight) Encoder(encoder string) *Highlight { hl.encoder = &encoder return hl } func (hl *Highlight) PreTags(preTags ...string) *Highlight { hl.preTags = append(hl.preTags, preTags...) return hl } func (hl *Highlight) PostTags(postTags ...string) *Highlight { hl.postTags = append(hl.postTags, postTags...) return hl } func (hl *Highlight) Order(order string) *Highlight { hl.order = &order return hl } func (hl *Highlight) RequireFieldMatch(requireFieldMatch bool) *Highlight { hl.requireFieldMatch = &requireFieldMatch return hl } func (hl *Highlight) MaxAnalyzedOffset(maxAnalyzedOffset int) *Highlight { hl.maxAnalyzedOffset = &maxAnalyzedOffset return hl } func (hl *Highlight) BoundaryMaxScan(boundaryMaxScan int) *Highlight { hl.boundaryMaxScan = &boundaryMaxScan return hl } func (hl *Highlight) BoundaryChars(boundaryChars string) *Highlight { hl.boundaryChars = &boundaryChars return hl } func (hl *Highlight) BoundaryScannerType(boundaryScannerType string) *Highlight { hl.boundaryScannerType = &boundaryScannerType return hl } func (hl *Highlight) BoundaryScannerLocale(boundaryScannerLocale string) *Highlight { hl.boundaryScannerLocale = &boundaryScannerLocale return hl } func (hl *Highlight) HighlighterType(highlighterType string) *Highlight { hl.highlighterType = &highlighterType return hl } func (hl *Highlight) Fragmenter(fragmenter string) *Highlight { hl.fragmenter = &fragmenter return hl } func (hl *Highlight) HighlightQuery(highlightQuery Query) *Highlight { hl.highlightQuery = highlightQuery return hl } func (hl *Highlight) NoMatchSize(noMatchSize int) *Highlight { hl.noMatchSize = &noMatchSize return hl } func (hl *Highlight) Options(options map[string]interface{}) *Highlight { hl.options = options return hl } func (hl *Highlight) ForceSource(forceSource bool) *Highlight { hl.forceSource = &forceSource return hl } func (hl *Highlight) UseExplicitFieldOrder(useExplicitFieldOrder bool) *Highlight { hl.useExplicitFieldOrder = useExplicitFieldOrder return hl } // Creates the query source for the bool query. func (hl *Highlight) Source() (interface{}, error) { // Returns the map inside of "highlight": // "highlight":{ // ... this ... // } source := make(map[string]interface{}) if hl.tagsSchema != nil { source["tags_schema"] = *hl.tagsSchema } if hl.preTags != nil && len(hl.preTags) > 0 { source["pre_tags"] = hl.preTags } if hl.postTags != nil && len(hl.postTags) > 0 { source["post_tags"] = hl.postTags } if hl.order != nil { source["order"] = *hl.order } if hl.highlightFilter != nil { source["highlight_filter"] = *hl.highlightFilter } if hl.fragmentSize != nil { source["fragment_size"] = *hl.fragmentSize } if hl.numOfFragments != nil { source["number_of_fragments"] = *hl.numOfFragments } if hl.encoder != nil { source["encoder"] = *hl.encoder } if hl.requireFieldMatch != nil { source["require_field_match"] = *hl.requireFieldMatch } if hl.maxAnalyzedOffset != nil { source["max_analyzed_offset"] = *hl.maxAnalyzedOffset } if hl.boundaryMaxScan != nil { source["boundary_max_scan"] = *hl.boundaryMaxScan } if hl.boundaryChars != nil { source["boundary_chars"] = *hl.boundaryChars } if hl.boundaryScannerType != nil { source["boundary_scanner"] = *hl.boundaryScannerType } if hl.boundaryScannerLocale != nil { source["boundary_scanner_locale"] = *hl.boundaryScannerLocale } if hl.highlighterType != nil { source["type"] = *hl.highlighterType } if hl.fragmenter != nil { source["fragmenter"] = *hl.fragmenter } if hl.highlightQuery != nil { src, err := hl.highlightQuery.Source() if err != nil { return nil, err } source["highlight_query"] = src } if hl.noMatchSize != nil { source["no_match_size"] = *hl.noMatchSize } if hl.phraseLimit != nil { source["phrase_limit"] = *hl.phraseLimit } if hl.options != nil && len(hl.options) > 0 { source["options"] = hl.options } if hl.forceSource != nil { source["force_source"] = *hl.forceSource } if hl.fields != nil && len(hl.fields) > 0 { if hl.useExplicitFieldOrder { // Use a slice for the fields var fields []map[string]interface{} for _, field := range hl.fields { src, err := field.Source() if err != nil { return nil, err } fmap := make(map[string]interface{}) fmap[field.Name] = src fields = append(fields, fmap) } source["fields"] = fields } else { // Use a map for the fields fields := make(map[string]interface{}) for _, field := range hl.fields { src, err := field.Source() if err != nil { return nil, err } fields[field.Name] = src } source["fields"] = fields } } return source, nil } // HighlighterField specifies a highlighted field. type HighlighterField struct { Name string preTags []string postTags []string fragmentSize int fragmentOffset int numOfFragments int highlightFilter *bool order *string requireFieldMatch *bool boundaryMaxScan int boundaryChars []rune highlighterType *string fragmenter *string highlightQuery Query noMatchSize *int matchedFields []string phraseLimit *int options map[string]interface{} forceSource *bool /* Name string preTags []string postTags []string fragmentSize int numOfFragments int fragmentOffset int highlightFilter *bool order string requireFieldMatch *bool boundaryMaxScan int boundaryChars []rune highlighterType string fragmenter string highlightQuery Query noMatchSize *int matchedFields []string options map[string]interface{} forceSource *bool */ } func NewHighlighterField(name string) *HighlighterField { return &HighlighterField{ Name: name, preTags: make([]string, 0), postTags: make([]string, 0), fragmentSize: -1, fragmentOffset: -1, numOfFragments: -1, boundaryMaxScan: -1, boundaryChars: make([]rune, 0), matchedFields: make([]string, 0), options: make(map[string]interface{}), } } func (f *HighlighterField) PreTags(preTags ...string) *HighlighterField { f.preTags = append(f.preTags, preTags...) return f } func (f *HighlighterField) PostTags(postTags ...string) *HighlighterField { f.postTags = append(f.postTags, postTags...) return f } func (f *HighlighterField) FragmentSize(fragmentSize int) *HighlighterField { f.fragmentSize = fragmentSize return f } func (f *HighlighterField) FragmentOffset(fragmentOffset int) *HighlighterField { f.fragmentOffset = fragmentOffset return f } func (f *HighlighterField) NumOfFragments(numOfFragments int) *HighlighterField { f.numOfFragments = numOfFragments return f } func (f *HighlighterField) HighlightFilter(highlightFilter bool) *HighlighterField { f.highlightFilter = &highlightFilter return f } func (f *HighlighterField) Order(order string) *HighlighterField { f.order = &order return f } func (f *HighlighterField) RequireFieldMatch(requireFieldMatch bool) *HighlighterField { f.requireFieldMatch = &requireFieldMatch return f } func (f *HighlighterField) BoundaryMaxScan(boundaryMaxScan int) *HighlighterField { f.boundaryMaxScan = boundaryMaxScan return f } func (f *HighlighterField) BoundaryChars(boundaryChars ...rune) *HighlighterField { f.boundaryChars = append(f.boundaryChars, boundaryChars...) return f } func (f *HighlighterField) HighlighterType(highlighterType string) *HighlighterField { f.highlighterType = &highlighterType return f } func (f *HighlighterField) Fragmenter(fragmenter string) *HighlighterField { f.fragmenter = &fragmenter return f } func (f *HighlighterField) HighlightQuery(highlightQuery Query) *HighlighterField { f.highlightQuery = highlightQuery return f } func (f *HighlighterField) NoMatchSize(noMatchSize int) *HighlighterField { f.noMatchSize = &noMatchSize return f } func (f *HighlighterField) Options(options map[string]interface{}) *HighlighterField { f.options = options return f } func (f *HighlighterField) MatchedFields(matchedFields ...string) *HighlighterField { f.matchedFields = append(f.matchedFields, matchedFields...) return f } func (f *HighlighterField) PhraseLimit(phraseLimit int) *HighlighterField { f.phraseLimit = &phraseLimit return f } func (f *HighlighterField) ForceSource(forceSource bool) *HighlighterField { f.forceSource = &forceSource return f } func (f *HighlighterField) Source() (interface{}, error) { source := make(map[string]interface{}) if f.preTags != nil && len(f.preTags) > 0 { source["pre_tags"] = f.preTags } if f.postTags != nil && len(f.postTags) > 0 { source["post_tags"] = f.postTags } if f.fragmentSize != -1 { source["fragment_size"] = f.fragmentSize } if f.numOfFragments != -1 { source["number_of_fragments"] = f.numOfFragments } if f.fragmentOffset != -1 { source["fragment_offset"] = f.fragmentOffset } if f.highlightFilter != nil { source["highlight_filter"] = *f.highlightFilter } if f.order != nil { source["order"] = *f.order } if f.requireFieldMatch != nil { source["require_field_match"] = *f.requireFieldMatch } if f.boundaryMaxScan != -1 { source["boundary_max_scan"] = f.boundaryMaxScan } if f.boundaryChars != nil && len(f.boundaryChars) > 0 { source["boundary_chars"] = f.boundaryChars } if f.highlighterType != nil { source["type"] = *f.highlighterType } if f.fragmenter != nil { source["fragmenter"] = *f.fragmenter } if f.highlightQuery != nil { src, err := f.highlightQuery.Source() if err != nil { return nil, err } source["highlight_query"] = src } if f.noMatchSize != nil { source["no_match_size"] = *f.noMatchSize } if f.matchedFields != nil && len(f.matchedFields) > 0 { source["matched_fields"] = f.matchedFields } if f.phraseLimit != nil { source["phrase_limit"] = *f.phraseLimit } if f.options != nil && len(f.options) > 0 { source["options"] = f.options } if f.forceSource != nil { source["force_source"] = *f.forceSource } return source, nil }