mirror of
https://codeberg.org/forgejo/forgejo
synced 2024-11-25 03:06:10 +01:00
5dbf36f356
* Issue search support elasticsearch * Fix lint * Add indexer name on app.ini * add a warnning on SearchIssuesByKeyword * improve code
470 lines
12 KiB
Go
Vendored
470 lines
12 KiB
Go
Vendored
// 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
|
|
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) 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.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
|
|
}
|