mirror of https://github.com/grafana/grafana
Search: Filter punctuation and tokenize camel case (#51165)
Co-authored-by: Ryan McKinley <ryantxu@gmail.com>pull/51560/head^2
parent
03c13742ac
commit
0975ea4df8
@ -0,0 +1,47 @@ |
||||
package searchV2 |
||||
|
||||
import ( |
||||
"strings" |
||||
|
||||
"github.com/blugelabs/bluge/analysis" |
||||
"github.com/blugelabs/bluge/analysis/token" |
||||
"github.com/blugelabs/bluge/analysis/tokenizer" |
||||
) |
||||
|
||||
var punctuationReplacer *strings.Replacer |
||||
|
||||
func init() { |
||||
var punctuation = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" |
||||
args := make([]string, 0, len(punctuation)*2) |
||||
for _, r := range punctuation { |
||||
args = append(args, string(r), " ") |
||||
} |
||||
punctuationReplacer = strings.NewReplacer(args...) |
||||
} |
||||
|
||||
type punctuationCharFilter struct{} |
||||
|
||||
func (t *punctuationCharFilter) Filter(input []byte) []byte { |
||||
return []byte(punctuationReplacer.Replace(string(input))) |
||||
} |
||||
|
||||
const ngramEdgeFilterMaxLength = 7 |
||||
|
||||
var ngramIndexAnalyzer = &analysis.Analyzer{ |
||||
CharFilters: []analysis.CharFilter{&punctuationCharFilter{}}, |
||||
Tokenizer: tokenizer.NewWhitespaceTokenizer(), |
||||
TokenFilters: []analysis.TokenFilter{ |
||||
token.NewCamelCaseFilter(), |
||||
token.NewLowerCaseFilter(), |
||||
token.NewEdgeNgramFilter(token.FRONT, 1, ngramEdgeFilterMaxLength), |
||||
}, |
||||
} |
||||
|
||||
var ngramQueryAnalyzer = &analysis.Analyzer{ |
||||
CharFilters: []analysis.CharFilter{&punctuationCharFilter{}}, |
||||
Tokenizer: tokenizer.NewWhitespaceTokenizer(), |
||||
TokenFilters: []analysis.TokenFilter{ |
||||
token.NewCamelCaseFilter(), |
||||
token.NewLowerCaseFilter(), |
||||
}, |
||||
} |
@ -0,0 +1,59 @@ |
||||
package searchV2 |
||||
|
||||
import ( |
||||
"reflect" |
||||
"testing" |
||||
|
||||
"github.com/stretchr/testify/require" |
||||
) |
||||
|
||||
func Test_punctuationCharFilter_Filter(t1 *testing.T) { |
||||
type args struct { |
||||
input []byte |
||||
} |
||||
tests := []struct { |
||||
name string |
||||
args args |
||||
want []byte |
||||
}{ |
||||
{ |
||||
name: "1", |
||||
args: args{ |
||||
input: []byte("x-Rays"), |
||||
}, |
||||
want: []byte("x Rays"), |
||||
}, |
||||
{ |
||||
name: "2", |
||||
args: args{ |
||||
input: []byte("x.Rays"), |
||||
}, |
||||
want: []byte("x Rays"), |
||||
}, |
||||
{ |
||||
name: "3", |
||||
args: args{ |
||||
input: []byte("[x,Rays]"), |
||||
}, |
||||
want: []byte(" x Rays "), |
||||
}, |
||||
} |
||||
for _, tt := range tests { |
||||
t1.Run(tt.name, func(t1 *testing.T) { |
||||
t := &punctuationCharFilter{} |
||||
if got := t.Filter(tt.args.input); !reflect.DeepEqual(got, tt.want) { |
||||
t1.Errorf("Filter() = %v, want %v", string(got), string(tt.want)) |
||||
} |
||||
}) |
||||
} |
||||
} |
||||
|
||||
func TestNgramIndexAnalyzer(t *testing.T) { |
||||
stream := ngramIndexAnalyzer.Analyze([]byte("x-rays.and.xRays, and НемногоКириллицы")) |
||||
expectedTerms := []string{"x", "r", "ra", "ray", "rays", "a", "an", "and", "x", "r", "ra", "ray", "rays", "a", "an", "and", "н", "не", "нем", "немн", "немно", "немног", "немного", "к", "ки", "кир", "кири", "кирил", "кирилл", "кирилли"} |
||||
var actualTerms []string |
||||
for _, t := range stream { |
||||
actualTerms = append(actualTerms, string(t.Term)) |
||||
} |
||||
require.Equal(t, expectedTerms, actualTerms) |
||||
} |
@ -0,0 +1,131 @@ |
||||
// 🌟 This was machine generated. Do not edit. 🌟 |
||||
// |
||||
// Frame[0] { |
||||
// "type": "search-results", |
||||
// "custom": { |
||||
// "count": 1 |
||||
// } |
||||
// } |
||||
// Name: Query results |
||||
// Dimensions: 8 Fields by 1 Rows |
||||
// +----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | |
||||
// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | |
||||
// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []*json.RawMessage | Type: []string | |
||||
// +----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// | dashboard | 1 | heatTorkel | | /pfix/d/1/ | null | null | | |
||||
// +----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// |
||||
// |
||||
// 🌟 This was machine generated. Do not edit. 🌟 |
||||
{ |
||||
"frames": [ |
||||
{ |
||||
"schema": { |
||||
"name": "Query results", |
||||
"meta": { |
||||
"type": "search-results", |
||||
"custom": { |
||||
"count": 1 |
||||
} |
||||
}, |
||||
"fields": [ |
||||
{ |
||||
"name": "kind", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "uid", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "name", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "panel_type", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "url", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
}, |
||||
"config": { |
||||
"links": [ |
||||
{ |
||||
"title": "link", |
||||
"url": "${__value.text}" |
||||
} |
||||
] |
||||
} |
||||
}, |
||||
{ |
||||
"name": "tags", |
||||
"type": "other", |
||||
"typeInfo": { |
||||
"frame": "json.RawMessage", |
||||
"nullable": true |
||||
} |
||||
}, |
||||
{ |
||||
"name": "ds_uid", |
||||
"type": "other", |
||||
"typeInfo": { |
||||
"frame": "json.RawMessage", |
||||
"nullable": true |
||||
} |
||||
}, |
||||
{ |
||||
"name": "location", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
"data": { |
||||
"values": [ |
||||
[ |
||||
"dashboard" |
||||
], |
||||
[ |
||||
"1" |
||||
], |
||||
[ |
||||
"heatTorkel" |
||||
], |
||||
[ |
||||
"" |
||||
], |
||||
[ |
||||
"/pfix/d/1/" |
||||
], |
||||
[ |
||||
null |
||||
], |
||||
[ |
||||
null |
||||
], |
||||
[ |
||||
"" |
||||
] |
||||
] |
||||
} |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,131 @@ |
||||
// 🌟 This was machine generated. Do not edit. 🌟 |
||||
// |
||||
// Frame[0] { |
||||
// "type": "search-results", |
||||
// "custom": { |
||||
// "count": 1 |
||||
// } |
||||
// } |
||||
// Name: Query results |
||||
// Dimensions: 8 Fields by 1 Rows |
||||
// +----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | |
||||
// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | |
||||
// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []*json.RawMessage | Type: []string | |
||||
// +----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// | dashboard | 1 | heat-torkel | | /pfix/d/1/ | null | null | | |
||||
// +----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// |
||||
// |
||||
// 🌟 This was machine generated. Do not edit. 🌟 |
||||
{ |
||||
"frames": [ |
||||
{ |
||||
"schema": { |
||||
"name": "Query results", |
||||
"meta": { |
||||
"type": "search-results", |
||||
"custom": { |
||||
"count": 1 |
||||
} |
||||
}, |
||||
"fields": [ |
||||
{ |
||||
"name": "kind", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "uid", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "name", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "panel_type", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "url", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
}, |
||||
"config": { |
||||
"links": [ |
||||
{ |
||||
"title": "link", |
||||
"url": "${__value.text}" |
||||
} |
||||
] |
||||
} |
||||
}, |
||||
{ |
||||
"name": "tags", |
||||
"type": "other", |
||||
"typeInfo": { |
||||
"frame": "json.RawMessage", |
||||
"nullable": true |
||||
} |
||||
}, |
||||
{ |
||||
"name": "ds_uid", |
||||
"type": "other", |
||||
"typeInfo": { |
||||
"frame": "json.RawMessage", |
||||
"nullable": true |
||||
} |
||||
}, |
||||
{ |
||||
"name": "location", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
"data": { |
||||
"values": [ |
||||
[ |
||||
"dashboard" |
||||
], |
||||
[ |
||||
"1" |
||||
], |
||||
[ |
||||
"heat-torkel" |
||||
], |
||||
[ |
||||
"" |
||||
], |
||||
[ |
||||
"/pfix/d/1/" |
||||
], |
||||
[ |
||||
null |
||||
], |
||||
[ |
||||
null |
||||
], |
||||
[ |
||||
"" |
||||
] |
||||
] |
||||
} |
||||
} |
||||
] |
||||
} |
@ -0,0 +1,140 @@ |
||||
// 🌟 This was machine generated. Do not edit. 🌟 |
||||
// |
||||
// Frame[0] { |
||||
// "type": "search-results", |
||||
// "custom": { |
||||
// "count": 2 |
||||
// } |
||||
// } |
||||
// Name: Query results |
||||
// Dimensions: 8 Fields by 2 Rows |
||||
// +----------------+----------------+------------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// | Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | |
||||
// | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | Labels: | |
||||
// | Type: []string | Type: []string | Type: []string | Type: []string | Type: []string | Type: []*json.RawMessage | Type: []*json.RawMessage | Type: []string | |
||||
// +----------------+----------------+------------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// | dashboard | 1 | heat-torkel | | /pfix/d/1/ | null | null | | |
||||
// | dashboard | 2 | topology heatmap | | /pfix/d/2/ | null | null | | |
||||
// +----------------+----------------+------------------+------------------+----------------+--------------------------+--------------------------+----------------+ |
||||
// |
||||
// |
||||
// 🌟 This was machine generated. Do not edit. 🌟 |
||||
{ |
||||
"frames": [ |
||||
{ |
||||
"schema": { |
||||
"name": "Query results", |
||||
"meta": { |
||||
"type": "search-results", |
||||
"custom": { |
||||
"count": 2 |
||||
} |
||||
}, |
||||
"fields": [ |
||||
{ |
||||
"name": "kind", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "uid", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "name", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "panel_type", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
}, |
||||
{ |
||||
"name": "url", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
}, |
||||
"config": { |
||||
"links": [ |
||||
{ |
||||
"title": "link", |
||||
"url": "${__value.text}" |
||||
} |
||||
] |
||||
} |
||||
}, |
||||
{ |
||||
"name": "tags", |
||||
"type": "other", |
||||
"typeInfo": { |
||||
"frame": "json.RawMessage", |
||||
"nullable": true |
||||
} |
||||
}, |
||||
{ |
||||
"name": "ds_uid", |
||||
"type": "other", |
||||
"typeInfo": { |
||||
"frame": "json.RawMessage", |
||||
"nullable": true |
||||
} |
||||
}, |
||||
{ |
||||
"name": "location", |
||||
"type": "string", |
||||
"typeInfo": { |
||||
"frame": "string" |
||||
} |
||||
} |
||||
] |
||||
}, |
||||
"data": { |
||||
"values": [ |
||||
[ |
||||
"dashboard", |
||||
"dashboard" |
||||
], |
||||
[ |
||||
"1", |
||||
"2" |
||||
], |
||||
[ |
||||
"heat-torkel", |
||||
"topology heatmap" |
||||
], |
||||
[ |
||||
"", |
||||
"" |
||||
], |
||||
[ |
||||
"/pfix/d/1/", |
||||
"/pfix/d/2/" |
||||
], |
||||
[ |
||||
null, |
||||
null |
||||
], |
||||
[ |
||||
null, |
||||
null |
||||
], |
||||
[ |
||||
"", |
||||
"" |
||||
] |
||||
] |
||||
} |
||||
} |
||||
] |
||||
} |
Loading…
Reference in new issue