mirror of
https://github.com/go-gitea/gitea.git
synced 2024-08-19 02:53:25 +02:00
451 lines
14 KiB
Go
451 lines
14 KiB
Go
|
// 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
|
||
|
|
||
|
// SignificantTermsAggregation is an aggregation that returns interesting
|
||
|
// or unusual occurrences of terms in a set.
|
||
|
// See: https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html
|
||
|
type SignificantTermsAggregation struct {
|
||
|
field string
|
||
|
subAggregations map[string]Aggregation
|
||
|
meta map[string]interface{}
|
||
|
|
||
|
minDocCount *int
|
||
|
shardMinDocCount *int
|
||
|
requiredSize *int
|
||
|
shardSize *int
|
||
|
filter Query
|
||
|
executionHint string
|
||
|
significanceHeuristic SignificanceHeuristic
|
||
|
includeExclude *TermsAggregationIncludeExclude
|
||
|
}
|
||
|
|
||
|
func NewSignificantTermsAggregation() *SignificantTermsAggregation {
|
||
|
return &SignificantTermsAggregation{
|
||
|
subAggregations: make(map[string]Aggregation),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) Field(field string) *SignificantTermsAggregation {
|
||
|
a.field = field
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) SubAggregation(name string, subAggregation Aggregation) *SignificantTermsAggregation {
|
||
|
a.subAggregations[name] = subAggregation
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
// Meta sets the meta data to be included in the aggregation response.
|
||
|
func (a *SignificantTermsAggregation) Meta(metaData map[string]interface{}) *SignificantTermsAggregation {
|
||
|
a.meta = metaData
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) MinDocCount(minDocCount int) *SignificantTermsAggregation {
|
||
|
a.minDocCount = &minDocCount
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) ShardMinDocCount(shardMinDocCount int) *SignificantTermsAggregation {
|
||
|
a.shardMinDocCount = &shardMinDocCount
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) RequiredSize(requiredSize int) *SignificantTermsAggregation {
|
||
|
a.requiredSize = &requiredSize
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) ShardSize(shardSize int) *SignificantTermsAggregation {
|
||
|
a.shardSize = &shardSize
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) BackgroundFilter(filter Query) *SignificantTermsAggregation {
|
||
|
a.filter = filter
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) ExecutionHint(hint string) *SignificantTermsAggregation {
|
||
|
a.executionHint = hint
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) SignificanceHeuristic(heuristic SignificanceHeuristic) *SignificantTermsAggregation {
|
||
|
a.significanceHeuristic = heuristic
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) Include(regexp string) *SignificantTermsAggregation {
|
||
|
if a.includeExclude == nil {
|
||
|
a.includeExclude = &TermsAggregationIncludeExclude{}
|
||
|
}
|
||
|
a.includeExclude.Include = regexp
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) IncludeValues(values ...interface{}) *SignificantTermsAggregation {
|
||
|
if a.includeExclude == nil {
|
||
|
a.includeExclude = &TermsAggregationIncludeExclude{}
|
||
|
}
|
||
|
a.includeExclude.IncludeValues = append(a.includeExclude.IncludeValues, values...)
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) Exclude(regexp string) *SignificantTermsAggregation {
|
||
|
if a.includeExclude == nil {
|
||
|
a.includeExclude = &TermsAggregationIncludeExclude{}
|
||
|
}
|
||
|
a.includeExclude.Exclude = regexp
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) ExcludeValues(values ...interface{}) *SignificantTermsAggregation {
|
||
|
if a.includeExclude == nil {
|
||
|
a.includeExclude = &TermsAggregationIncludeExclude{}
|
||
|
}
|
||
|
a.includeExclude.ExcludeValues = append(a.includeExclude.ExcludeValues, values...)
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) Partition(p int) *SignificantTermsAggregation {
|
||
|
if a.includeExclude == nil {
|
||
|
a.includeExclude = &TermsAggregationIncludeExclude{}
|
||
|
}
|
||
|
a.includeExclude.Partition = p
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) NumPartitions(n int) *SignificantTermsAggregation {
|
||
|
if a.includeExclude == nil {
|
||
|
a.includeExclude = &TermsAggregationIncludeExclude{}
|
||
|
}
|
||
|
a.includeExclude.NumPartitions = n
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) IncludeExclude(includeExclude *TermsAggregationIncludeExclude) *SignificantTermsAggregation {
|
||
|
a.includeExclude = includeExclude
|
||
|
return a
|
||
|
}
|
||
|
|
||
|
func (a *SignificantTermsAggregation) Source() (interface{}, error) {
|
||
|
// Example:
|
||
|
// {
|
||
|
// "query" : {
|
||
|
// "terms" : {"force" : [ "British Transport Police" ]}
|
||
|
// },
|
||
|
// "aggregations" : {
|
||
|
// "significantCrimeTypes" : {
|
||
|
// "significant_terms" : { "field" : "crime_type" }
|
||
|
// }
|
||
|
// }
|
||
|
// }
|
||
|
//
|
||
|
// This method returns only the
|
||
|
// { "significant_terms" : { "field" : "crime_type" }
|
||
|
// part.
|
||
|
|
||
|
source := make(map[string]interface{})
|
||
|
opts := make(map[string]interface{})
|
||
|
source["significant_terms"] = opts
|
||
|
|
||
|
if a.field != "" {
|
||
|
opts["field"] = a.field
|
||
|
}
|
||
|
if a.requiredSize != nil {
|
||
|
opts["size"] = *a.requiredSize // not a typo!
|
||
|
}
|
||
|
if a.shardSize != nil {
|
||
|
opts["shard_size"] = *a.shardSize
|
||
|
}
|
||
|
if a.minDocCount != nil {
|
||
|
opts["min_doc_count"] = *a.minDocCount
|
||
|
}
|
||
|
if a.shardMinDocCount != nil {
|
||
|
opts["shard_min_doc_count"] = *a.shardMinDocCount
|
||
|
}
|
||
|
if a.executionHint != "" {
|
||
|
opts["execution_hint"] = a.executionHint
|
||
|
}
|
||
|
if a.filter != nil {
|
||
|
src, err := a.filter.Source()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
opts["background_filter"] = src
|
||
|
}
|
||
|
if a.significanceHeuristic != nil {
|
||
|
name := a.significanceHeuristic.Name()
|
||
|
src, err := a.significanceHeuristic.Source()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
opts[name] = src
|
||
|
}
|
||
|
|
||
|
// Include/Exclude
|
||
|
if ie := a.includeExclude; ie != nil {
|
||
|
if err := ie.MergeInto(opts); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// AggregationBuilder (SubAggregations)
|
||
|
if len(a.subAggregations) > 0 {
|
||
|
aggsMap := make(map[string]interface{})
|
||
|
source["aggregations"] = aggsMap
|
||
|
for name, aggregate := range a.subAggregations {
|
||
|
src, err := aggregate.Source()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
aggsMap[name] = src
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Add Meta data if available
|
||
|
if len(a.meta) > 0 {
|
||
|
source["meta"] = a.meta
|
||
|
}
|
||
|
|
||
|
return source, nil
|
||
|
}
|
||
|
|
||
|
// -- Significance heuristics --
|
||
|
|
||
|
type SignificanceHeuristic interface {
|
||
|
Name() string
|
||
|
Source() (interface{}, error)
|
||
|
}
|
||
|
|
||
|
// -- Chi Square --
|
||
|
|
||
|
// ChiSquareSignificanceHeuristic implements Chi square as described
|
||
|
// in "Information Retrieval", Manning et al., Chapter 13.5.2.
|
||
|
//
|
||
|
// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_chi_square
|
||
|
// for details.
|
||
|
type ChiSquareSignificanceHeuristic struct {
|
||
|
backgroundIsSuperset *bool
|
||
|
includeNegatives *bool
|
||
|
}
|
||
|
|
||
|
// NewChiSquareSignificanceHeuristic initializes a new ChiSquareSignificanceHeuristic.
|
||
|
func NewChiSquareSignificanceHeuristic() *ChiSquareSignificanceHeuristic {
|
||
|
return &ChiSquareSignificanceHeuristic{}
|
||
|
}
|
||
|
|
||
|
// Name returns the name of the heuristic in the REST interface.
|
||
|
func (sh *ChiSquareSignificanceHeuristic) Name() string {
|
||
|
return "chi_square"
|
||
|
}
|
||
|
|
||
|
// BackgroundIsSuperset indicates whether you defined a custom background
|
||
|
// filter that represents a difference set of documents that you want to
|
||
|
// compare to.
|
||
|
func (sh *ChiSquareSignificanceHeuristic) BackgroundIsSuperset(backgroundIsSuperset bool) *ChiSquareSignificanceHeuristic {
|
||
|
sh.backgroundIsSuperset = &backgroundIsSuperset
|
||
|
return sh
|
||
|
}
|
||
|
|
||
|
// IncludeNegatives indicates whether to filter out the terms that appear
|
||
|
// much less in the subset than in the background without the subset.
|
||
|
func (sh *ChiSquareSignificanceHeuristic) IncludeNegatives(includeNegatives bool) *ChiSquareSignificanceHeuristic {
|
||
|
sh.includeNegatives = &includeNegatives
|
||
|
return sh
|
||
|
}
|
||
|
|
||
|
// Source returns the parameters that need to be added to the REST parameters.
|
||
|
func (sh *ChiSquareSignificanceHeuristic) Source() (interface{}, error) {
|
||
|
source := make(map[string]interface{})
|
||
|
if sh.backgroundIsSuperset != nil {
|
||
|
source["background_is_superset"] = *sh.backgroundIsSuperset
|
||
|
}
|
||
|
if sh.includeNegatives != nil {
|
||
|
source["include_negatives"] = *sh.includeNegatives
|
||
|
}
|
||
|
return source, nil
|
||
|
}
|
||
|
|
||
|
// -- GND --
|
||
|
|
||
|
// GNDSignificanceHeuristic implements the "Google Normalized Distance"
|
||
|
// as described in "The Google Similarity Distance", Cilibrasi and Vitanyi,
|
||
|
// 2007.
|
||
|
//
|
||
|
// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_google_normalized_distance
|
||
|
// for details.
|
||
|
type GNDSignificanceHeuristic struct {
|
||
|
backgroundIsSuperset *bool
|
||
|
}
|
||
|
|
||
|
// NewGNDSignificanceHeuristic implements a new GNDSignificanceHeuristic.
|
||
|
func NewGNDSignificanceHeuristic() *GNDSignificanceHeuristic {
|
||
|
return &GNDSignificanceHeuristic{}
|
||
|
}
|
||
|
|
||
|
// Name returns the name of the heuristic in the REST interface.
|
||
|
func (sh *GNDSignificanceHeuristic) Name() string {
|
||
|
return "gnd"
|
||
|
}
|
||
|
|
||
|
// BackgroundIsSuperset indicates whether you defined a custom background
|
||
|
// filter that represents a difference set of documents that you want to
|
||
|
// compare to.
|
||
|
func (sh *GNDSignificanceHeuristic) BackgroundIsSuperset(backgroundIsSuperset bool) *GNDSignificanceHeuristic {
|
||
|
sh.backgroundIsSuperset = &backgroundIsSuperset
|
||
|
return sh
|
||
|
}
|
||
|
|
||
|
// Source returns the parameters that need to be added to the REST parameters.
|
||
|
func (sh *GNDSignificanceHeuristic) Source() (interface{}, error) {
|
||
|
source := make(map[string]interface{})
|
||
|
if sh.backgroundIsSuperset != nil {
|
||
|
source["background_is_superset"] = *sh.backgroundIsSuperset
|
||
|
}
|
||
|
return source, nil
|
||
|
}
|
||
|
|
||
|
// -- JLH Score --
|
||
|
|
||
|
// JLHScoreSignificanceHeuristic implements the JLH score as described in
|
||
|
// https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_jlh_score.
|
||
|
type JLHScoreSignificanceHeuristic struct{}
|
||
|
|
||
|
// NewJLHScoreSignificanceHeuristic initializes a new JLHScoreSignificanceHeuristic.
|
||
|
func NewJLHScoreSignificanceHeuristic() *JLHScoreSignificanceHeuristic {
|
||
|
return &JLHScoreSignificanceHeuristic{}
|
||
|
}
|
||
|
|
||
|
// Name returns the name of the heuristic in the REST interface.
|
||
|
func (sh *JLHScoreSignificanceHeuristic) Name() string {
|
||
|
return "jlh"
|
||
|
}
|
||
|
|
||
|
// Source returns the parameters that need to be added to the REST parameters.
|
||
|
func (sh *JLHScoreSignificanceHeuristic) Source() (interface{}, error) {
|
||
|
source := make(map[string]interface{})
|
||
|
return source, nil
|
||
|
}
|
||
|
|
||
|
// -- Mutual Information --
|
||
|
|
||
|
// MutualInformationSignificanceHeuristic implements Mutual information
|
||
|
// as described in "Information Retrieval", Manning et al., Chapter 13.5.1.
|
||
|
//
|
||
|
// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_mutual_information
|
||
|
// for details.
|
||
|
type MutualInformationSignificanceHeuristic struct {
|
||
|
backgroundIsSuperset *bool
|
||
|
includeNegatives *bool
|
||
|
}
|
||
|
|
||
|
// NewMutualInformationSignificanceHeuristic initializes a new instance of
|
||
|
// MutualInformationSignificanceHeuristic.
|
||
|
func NewMutualInformationSignificanceHeuristic() *MutualInformationSignificanceHeuristic {
|
||
|
return &MutualInformationSignificanceHeuristic{}
|
||
|
}
|
||
|
|
||
|
// Name returns the name of the heuristic in the REST interface.
|
||
|
func (sh *MutualInformationSignificanceHeuristic) Name() string {
|
||
|
return "mutual_information"
|
||
|
}
|
||
|
|
||
|
// BackgroundIsSuperset indicates whether you defined a custom background
|
||
|
// filter that represents a difference set of documents that you want to
|
||
|
// compare to.
|
||
|
func (sh *MutualInformationSignificanceHeuristic) BackgroundIsSuperset(backgroundIsSuperset bool) *MutualInformationSignificanceHeuristic {
|
||
|
sh.backgroundIsSuperset = &backgroundIsSuperset
|
||
|
return sh
|
||
|
}
|
||
|
|
||
|
// IncludeNegatives indicates whether to filter out the terms that appear
|
||
|
// much less in the subset than in the background without the subset.
|
||
|
func (sh *MutualInformationSignificanceHeuristic) IncludeNegatives(includeNegatives bool) *MutualInformationSignificanceHeuristic {
|
||
|
sh.includeNegatives = &includeNegatives
|
||
|
return sh
|
||
|
}
|
||
|
|
||
|
// Source returns the parameters that need to be added to the REST parameters.
|
||
|
func (sh *MutualInformationSignificanceHeuristic) Source() (interface{}, error) {
|
||
|
source := make(map[string]interface{})
|
||
|
if sh.backgroundIsSuperset != nil {
|
||
|
source["background_is_superset"] = *sh.backgroundIsSuperset
|
||
|
}
|
||
|
if sh.includeNegatives != nil {
|
||
|
source["include_negatives"] = *sh.includeNegatives
|
||
|
}
|
||
|
return source, nil
|
||
|
}
|
||
|
|
||
|
// -- Percentage Score --
|
||
|
|
||
|
// PercentageScoreSignificanceHeuristic implements the algorithm described
|
||
|
// in https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_percentage.
|
||
|
type PercentageScoreSignificanceHeuristic struct{}
|
||
|
|
||
|
// NewPercentageScoreSignificanceHeuristic initializes a new instance of
|
||
|
// PercentageScoreSignificanceHeuristic.
|
||
|
func NewPercentageScoreSignificanceHeuristic() *PercentageScoreSignificanceHeuristic {
|
||
|
return &PercentageScoreSignificanceHeuristic{}
|
||
|
}
|
||
|
|
||
|
// Name returns the name of the heuristic in the REST interface.
|
||
|
func (sh *PercentageScoreSignificanceHeuristic) Name() string {
|
||
|
return "percentage"
|
||
|
}
|
||
|
|
||
|
// Source returns the parameters that need to be added to the REST parameters.
|
||
|
func (sh *PercentageScoreSignificanceHeuristic) Source() (interface{}, error) {
|
||
|
source := make(map[string]interface{})
|
||
|
return source, nil
|
||
|
}
|
||
|
|
||
|
// -- Script --
|
||
|
|
||
|
// ScriptSignificanceHeuristic implements a scripted significance heuristic.
|
||
|
// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_scripted
|
||
|
// for details.
|
||
|
type ScriptSignificanceHeuristic struct {
|
||
|
script *Script
|
||
|
}
|
||
|
|
||
|
// NewScriptSignificanceHeuristic initializes a new instance of
|
||
|
// ScriptSignificanceHeuristic.
|
||
|
func NewScriptSignificanceHeuristic() *ScriptSignificanceHeuristic {
|
||
|
return &ScriptSignificanceHeuristic{}
|
||
|
}
|
||
|
|
||
|
// Name returns the name of the heuristic in the REST interface.
|
||
|
func (sh *ScriptSignificanceHeuristic) Name() string {
|
||
|
return "script_heuristic"
|
||
|
}
|
||
|
|
||
|
// Script specifies the script to use to get custom scores. The following
|
||
|
// parameters are available in the script: `_subset_freq`, `_superset_freq`,
|
||
|
// `_subset_size`, and `_superset_size`.
|
||
|
//
|
||
|
// See https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-aggregations-bucket-significantterms-aggregation.html#_scripted
|
||
|
// for details.
|
||
|
func (sh *ScriptSignificanceHeuristic) Script(script *Script) *ScriptSignificanceHeuristic {
|
||
|
sh.script = script
|
||
|
return sh
|
||
|
}
|
||
|
|
||
|
// Source returns the parameters that need to be added to the REST parameters.
|
||
|
func (sh *ScriptSignificanceHeuristic) Source() (interface{}, error) {
|
||
|
source := make(map[string]interface{})
|
||
|
if sh.script != nil {
|
||
|
src, err := sh.script.Source()
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
source["script"] = src
|
||
|
}
|
||
|
return source, nil
|
||
|
}
|