From e1f5d698e6454bc1f88a868cf3fe1ddfa035b126 Mon Sep 17 00:00:00 2001 From: Artur Wierzbicki Date: Fri, 9 Sep 2022 14:20:20 +0200 Subject: [PATCH] Search: Add substring matcher (#54895) * Search: Add substring matcher (#54813) * search: bring back substring search * lint fix * search: bring back ngram * search: bring back ngram * search: more tests * fix tests --- pkg/services/searchV2/bluge.go | 45 +++-- pkg/services/searchV2/index_test.go | 160 ++++++++++++++++++ pkg/services/searchV2/substring_query.go | 102 +++++++++++ .../ordering-tests-1-[Prometheus_2.].jsonc | 53 ++++++ .../testdata/ordering-tests-2-[Prome].jsonc | 59 +++++++ .../ordering-tests-3-[Prometheus_stat].jsonc | 50 ++++++ .../testdata/ordering-tests-4-[Loki_2.].jsonc | 62 +++++++ .../testdata/ordering-tests-5-[Lok].jsonc | 71 ++++++++ .../ordering-tests-6-[Loki_stats].jsonc | 53 ++++++ .../scattered-tokens-match-reversed.jsonc | 60 ++----- .../testdata/scattered-tokens-match.jsonc | 21 +-- 11 files changed, 662 insertions(+), 74 deletions(-) create mode 100644 pkg/services/searchV2/substring_query.go create mode 100644 pkg/services/searchV2/testdata/ordering-tests-1-[Prometheus_2.].jsonc create mode 100644 pkg/services/searchV2/testdata/ordering-tests-2-[Prome].jsonc create mode 100644 pkg/services/searchV2/testdata/ordering-tests-3-[Prometheus_stat].jsonc create mode 100644 pkg/services/searchV2/testdata/ordering-tests-4-[Loki_2.].jsonc create mode 100644 pkg/services/searchV2/testdata/ordering-tests-5-[Lok].jsonc create mode 100644 pkg/services/searchV2/testdata/ordering-tests-6-[Loki_stats].jsonc diff --git a/pkg/services/searchV2/bluge.go b/pkg/services/searchV2/bluge.go index 79234085b12..d4821dec4ba 100644 --- a/pkg/services/searchV2/bluge.go +++ b/pkg/services/searchV2/bluge.go @@ -24,7 +24,6 @@ const ( documentFieldName = "name" documentFieldName_sort = "name_sort" documentFieldName_ngram = "name_ngram" - documentFieldDescription = "description" documentFieldLocation = "location" // parent path documentFieldPanelType = "panel_type" documentFieldTransformer = "transformer" @@ -232,14 +231,11 @@ func newSearchDocument(uid string, name string, descr string, url string) *bluge doc.AddField(bluge.NewTextField(documentFieldName_ngram, name).WithAnalyzer(ngramIndexAnalyzer)) // Don't add a field for empty names - sortStr := strings.Trim(strings.ToUpper(name), " ") + sortStr := formatForNameSortField(name) if len(sortStr) > 0 { doc.AddField(bluge.NewKeywordField(documentFieldName_sort, sortStr).Sortable()) } } - if descr != "" { - doc.AddField(bluge.NewTextField(documentFieldDescription, descr).SearchTermPositions()) - } if url != "" { doc.AddField(bluge.NewKeywordField(documentFieldURL, url).StoreValue()) } @@ -435,21 +431,19 @@ func doSearchQuery( fullQuery.AddShould(bluge.NewMatchAllQuery()) } } else { - // The actual se - bq := bluge.NewBooleanQuery(). - AddShould(bluge.NewMatchQuery(q.Query).SetField(documentFieldName).SetBoost(6)). - AddShould(bluge.NewMatchQuery(q.Query).SetField(documentFieldDescription).SetBoost(3)). - AddShould(bluge.NewMatchQuery(q.Query). + bq := bluge.NewBooleanQuery() + + bq.AddShould(NewSubstringQuery(formatForNameSortField(q.Query)). + SetField(documentFieldName_sort). + SetBoost(6)) + + if shouldUseNgram(q) { + bq.AddShould(bluge.NewMatchQuery(q.Query). SetField(documentFieldName_ngram). SetOperator(bluge.MatchQueryOperatorAnd). // all terms must match SetAnalyzer(ngramQueryAnalyzer).SetBoost(1)) + } - if len(q.Query) > 4 { - bq.AddShould(bluge.NewFuzzyQuery(q.Query).SetField(documentFieldName)).SetBoost(1.5) - } - if len(q.Query) > ngramEdgeFilterMaxLength && !strings.Contains(q.Query, " ") { - bq.AddShould(bluge.NewPrefixQuery(strings.ToLower(q.Query)).SetField(documentFieldName)).SetBoost(6) - } fullQuery.AddMust(bq) } @@ -664,6 +658,25 @@ func doSearchQuery( return response } +func shouldUseNgram(q DashboardQuery) bool { + var tokens []string + if len(q.Query) > ngramEdgeFilterMaxLength { + tokens = strings.Fields(q.Query) + for _, k := range tokens { + // ngram will never match if at least one input token exceeds the max token length, + // as all tokens must match simultaneously with the `bluge.MatchQueryOperatorAnd` operator + if len(k) > ngramEdgeFilterMaxLength { + return false + } + } + } + return true +} + +func formatForNameSortField(name string) string { + return strings.Trim(strings.ToUpper(name), " ") +} + func getLocationLookupInfo(ctx context.Context, reader *bluge.Reader, uids map[string]bool) map[string]locationItem { res := make(map[string]locationItem, len(uids)) bq := bluge.NewBooleanQuery() diff --git a/pkg/services/searchV2/index_test.go b/pkg/services/searchV2/index_test.go index 972899b6788..07960520962 100644 --- a/pkg/services/searchV2/index_test.go +++ b/pkg/services/searchV2/index_test.go @@ -6,6 +6,7 @@ import ( "path/filepath" "testing" + "github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana/pkg/infra/log" @@ -82,6 +83,33 @@ func checkSearchResponseExtended(t *testing.T, fileName string, index *orgIndex, experimental.CheckGoldenJSONResponse(t, "testdata", fileName, resp, true) } +func getFrameWithNames(resp *backend.DataResponse) *data.Frame { + if resp == nil || len(resp.Frames) == 0 { + return nil + } + + frame := resp.Frames[0] + nameField, idx := frame.FieldByName(documentFieldName) + if nameField.Len() == 0 || idx == -1 { + return nil + } + + scoreField, _ := frame.FieldByName("score") + return data.NewFrame("ordering frame", nameField, scoreField) +} + +func checkSearchResponseOrdering(t *testing.T, fileName string, index *orgIndex, filter ResourceFilter, query DashboardQuery) { + t.Helper() + checkSearchResponseOrderingExtended(t, fileName, index, filter, query, &NoopQueryExtender{}) +} + +func checkSearchResponseOrderingExtended(t *testing.T, fileName string, index *orgIndex, filter ResourceFilter, query DashboardQuery, extender QueryExtender) { + t.Helper() + query.Explain = true + resp := doSearchQuery(context.Background(), testLogger, index, filter, query, extender, "/pfix") + experimental.CheckGoldenJSONFrame(t, "testdata", fileName, getFrameWithNames(resp), true) +} + var testDashboards = []dashboard{ { id: 1, @@ -582,3 +610,135 @@ func TestDashboardIndex_CamelCaseNgram(t *testing.T) { ) }) } + +func dashboardsWithTitles(names ...string) []dashboard { + out := make([]dashboard, 0) + for i, name := range names { + no := int64(i + 1) + out = append(out, dashboard{ + id: no, + uid: fmt.Sprintf("%d", no), + info: &extract.DashboardInfo{ + Title: name, + }, + }) + } + + return out +} + +func TestDashboardIndex_MultiTermPrefixMatch(t *testing.T) { + var tests = []struct { + dashboards []dashboard + query string + }{ + { + dashboards: dashboardsWithTitles( + "Panel Tests - Bar Gauge 2", + "Prometheus 2.0", + "Prometheus 2.0 Stats", + "Prometheus 20.0", + "Prometheus Second Word", + "Prometheus Stats", + "dynamic (2)", + "prometheus histogram", + "prometheus histogram2", + "roci-simple-2", + "x not y", + ), + query: "Prometheus 2.", + }, + { + dashboards: dashboardsWithTitles( + "From AAA", + "Grafana Dev Overview & Home", + "Home automation", + "Prometheus 2.0", + "Prometheus 2.0 Stats", + "Prometheus 20.0", + "Prometheus Stats", + "Transforms - config from query", + "iot-testing", + "prom style with exemplars", + "prop history", + "simple frame", + "with-hide-from", + "xy broke", + ), + query: "Prome", + }, + { + dashboards: dashboardsWithTitles( + "Panel Tests - Bar Gauge 2", + "Prometheus 2.0", + "Prometheus 2.0 Stats", + "Prometheus 20.0", + "Prometheus Second Word", + "Prometheus Stats", + "dynamic (2)", + "prometheus histogram", + "prometheus histogram2", + "roci-simple-2", + "x not y", + ), + query: "Prometheus stat", + }, + { + dashboards: dashboardsWithTitles( + "Loki Tests - Bar Gauge 2", + "Loki 2.0", + "Loki 2.0 Stats", + "Loki 20.0", + "Loki Second Word", + "Loki Stats", + "dynamic (2)", + "Loki histogram", + "Loki histogram2", + "roci-simple-2", + "x not y", + ), + query: "Loki 2.", + }, + { + dashboards: dashboardsWithTitles( + "Loki Tests - Bar Gauge 2", + "Loki 2.0", + "Loki 2.0 Stats", + "Loki 20.0", + "Loki Second Word", + "Loki Stats", + "dynamic (2)", + "Loki histogram", + "Loki histogram2", + "roci-simple-2", + "x not y", + ), + query: "Lok", + }, + { + dashboards: dashboardsWithTitles( + "Loki Tests - Bar Gauge 2", + "Loki 2.0", + "Loki 2.0 Stats", + "Loki 20.0", + "Loki Second Word", + "Loki Stats", + "dynamic (2)", + "Loki histogram", + "Loki histogram2", + "roci-simple-2", + "x not y", + ), + query: "Loki stats", + }, + } + + for i, tt := range tests { + t.Run(fmt.Sprintf("ordering-tests-%d-[%s]", i+1, tt.query), func(t *testing.T) { + index := initTestOrgIndexFromDashes(t, tt.dashboards) + checkSearchResponseOrdering(t, filepath.Base(t.Name()), index, testAllowAllFilter, + DashboardQuery{Query: tt.query}, + ) + }) + } +} diff --git a/pkg/services/searchV2/substring_query.go b/pkg/services/searchV2/substring_query.go new file mode 100644 index 00000000000..338ae74d798 --- /dev/null +++ b/pkg/services/searchV2/substring_query.go @@ -0,0 +1,102 @@ +// based on https://github.com/blugelabs/bluge/blob/57414197005148539c5dc5db8ab581594969df79/query.go#L1407-L1482, license: +// Copyright (c) 2020 Couchbase, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package searchV2 + +import ( + "strings" + + "github.com/blugelabs/bluge/search" + "github.com/blugelabs/bluge/search/searcher" + "github.com/blugelabs/bluge/search/similarity" +) + +type boost float64 + +func (b *boost) Value() float64 { + if b == nil { + return 1 + } + return float64(*b) +} + +type SubstringQuery struct { + substring string + field string + boost *boost + scorer search.Scorer +} + +func NewSubstringQuery(wildcard string) *SubstringQuery { + return &SubstringQuery{ + substring: wildcard, + } +} + +// Wildcard returns the substring being queried +func (q *SubstringQuery) Wildcard() string { + return q.substring +} + +func (q *SubstringQuery) SetBoost(b float64) *SubstringQuery { + boostVal := boost(b) + q.boost = &boostVal + return q +} + +func (q *SubstringQuery) Boost() float64 { + return q.boost.Value() +} + +func (q *SubstringQuery) SetField(f string) *SubstringQuery { + q.field = f + return q +} + +func (q *SubstringQuery) Field() string { + return q.field +} + +var regexpEscaper = strings.NewReplacer( + // characters in the substring that must + // be escaped in the regexp + "+", `\+`, + "*", `\*`, + "(", `\(`, + ")", `\)`, + "^", `\^`, + "$", `\$`, + ".", `\.`, + "{", `\{`, + "}", `\}`, + "[", `\[`, + "]", `\]`, + `|`, `\|`, + `\`, `\\`) + +func (q *SubstringQuery) Searcher(i search.Reader, options search.SearcherOptions) (search.Searcher, error) { + field := q.field + if q.field == "" { + field = options.DefaultSearchField + } + + regexpString := ".*" + regexpEscaper.Replace(q.substring) + ".*" + return searcher.NewRegexpStringSearcher(i, regexpString, field, + q.boost.Value(), q.scorer, similarity.NewCompositeSumScorer(), options) +} + +func (q *SubstringQuery) Validate() error { + return nil // real validation delayed until searcher constructor +} diff --git a/pkg/services/searchV2/testdata/ordering-tests-1-[Prometheus_2.].jsonc b/pkg/services/searchV2/testdata/ordering-tests-1-[Prometheus_2.].jsonc new file mode 100644 index 00000000000..ffa32662779 --- /dev/null +++ b/pkg/services/searchV2/testdata/ordering-tests-1-[Prometheus_2.].jsonc @@ -0,0 +1,53 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] +// Name: ordering frame +// Dimensions: 2 Fields by 2 Rows +// +----------------------+-------------------+ +// | Name: name | Name: score | +// | Labels: | Labels: | +// | Type: []string | Type: []float64 | +// +----------------------+-------------------+ +// | Prometheus 2.0 | 7.621131552585596 | +// | Prometheus 2.0 Stats | 7.621131552585596 | +// +----------------------+-------------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "frames": [ + { + "schema": { + "name": "ordering frame", + "fields": [ + { + "name": "name", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "score", + "type": "number", + "typeInfo": { + "frame": "float64" + } + } + ] + }, + "data": { + "values": [ + [ + "Prometheus 2.0", + "Prometheus 2.0 Stats" + ], + [ + 7.621131552585596, + 7.621131552585596 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-2-[Prome].jsonc b/pkg/services/searchV2/testdata/ordering-tests-2-[Prome].jsonc new file mode 100644 index 00000000000..339334effda --- /dev/null +++ b/pkg/services/searchV2/testdata/ordering-tests-2-[Prome].jsonc @@ -0,0 +1,59 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] +// Name: ordering frame +// Dimensions: 2 Fields by 4 Rows +// +----------------------+-------------------+ +// | Name: name | Name: score | +// | Labels: | Labels: | +// | Type: []string | Type: []float64 | +// +----------------------+-------------------+ +// | Prometheus 2.0 | 9.502378631081775 | +// | Prometheus 20.0 | 9.458475876581684 | +// | Prometheus Stats | 9.379374926302209 | +// | Prometheus 2.0 Stats | 9.310081326315688 | +// +----------------------+-------------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "frames": [ + { + "schema": { + "name": "ordering frame", + "fields": [ + { + "name": "name", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "score", + "type": "number", + "typeInfo": { + "frame": "float64" + } + } + ] + }, + "data": { + "values": [ + [ + "Prometheus 2.0", + "Prometheus 20.0", + "Prometheus Stats", + "Prometheus 2.0 Stats" + ], + [ + 9.502378631081775, + 9.458475876581684, + 9.379374926302209, + 9.310081326315688 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-3-[Prometheus_stat].jsonc b/pkg/services/searchV2/testdata/ordering-tests-3-[Prometheus_stat].jsonc new file mode 100644 index 00000000000..fdb6f06d0b6 --- /dev/null +++ b/pkg/services/searchV2/testdata/ordering-tests-3-[Prometheus_stat].jsonc @@ -0,0 +1,50 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] +// Name: ordering frame +// Dimensions: 2 Fields by 1 Rows +// +------------------+-------------------+ +// | Name: name | Name: score | +// | Labels: | Labels: | +// | Type: []string | Type: []float64 | +// +------------------+-------------------+ +// | Prometheus Stats | 7.621131552585596 | +// +------------------+-------------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "frames": [ + { + "schema": { + "name": "ordering frame", + "fields": [ + { + "name": "name", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "score", + "type": "number", + "typeInfo": { + "frame": "float64" + } + } + ] + }, + "data": { + "values": [ + [ + "Prometheus Stats" + ], + [ + 7.621131552585596 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-4-[Loki_2.].jsonc b/pkg/services/searchV2/testdata/ordering-tests-4-[Loki_2.].jsonc new file mode 100644 index 00000000000..9a2386e770c --- /dev/null +++ b/pkg/services/searchV2/testdata/ordering-tests-4-[Loki_2.].jsonc @@ -0,0 +1,62 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] +// Name: ordering frame +// Dimensions: 2 Fields by 5 Rows +// +--------------------------+--------------------+ +// | Name: name | Name: score | +// | Labels: | Labels: | +// | Type: []string | Type: []float64 | +// +--------------------------+--------------------+ +// | Loki 2.0 | 9.273036652923247 | +// | Loki 2.0 Stats | 8.951742733604135 | +// | Loki 20.0 | 2.57580523764178 | +// | Loki histogram2 | 2.2807887502617943 | +// | Loki Tests - Bar Gauge 2 | 2.045832444623899 | +// +--------------------------+--------------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "frames": [ + { + "schema": { + "name": "ordering frame", + "fields": [ + { + "name": "name", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "score", + "type": "number", + "typeInfo": { + "frame": "float64" + } + } + ] + }, + "data": { + "values": [ + [ + "Loki 2.0", + "Loki 2.0 Stats", + "Loki 20.0", + "Loki histogram2", + "Loki Tests - Bar Gauge 2" + ], + [ + 9.273036652923247, + 8.951742733604135, + 2.57580523764178, + 2.2807887502617943, + 2.045832444623899 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-5-[Lok].jsonc b/pkg/services/searchV2/testdata/ordering-tests-5-[Lok].jsonc new file mode 100644 index 00000000000..29812abae4a --- /dev/null +++ b/pkg/services/searchV2/testdata/ordering-tests-5-[Lok].jsonc @@ -0,0 +1,71 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] +// Name: ordering frame +// Dimensions: 2 Fields by 8 Rows +// +--------------------------+-------------------+ +// | Name: name | Name: score | +// | Labels: | Labels: | +// | Type: []string | Type: []float64 | +// +--------------------------+-------------------+ +// | Loki 2.0 | 8.386497572003142 | +// | Loki 20.0 | 8.351238737232393 | +// | Loki Stats | 8.289644692681875 | +// | Loki 2.0 Stats | 8.237634633059454 | +// | Loki histogram | 8.237634633059454 | +// | Loki histogram2 | 8.214550743132483 | +// | Loki Second Word | 8.173207674966303 | +// | Loki Tests - Bar Gauge 2 | 8.105690026892566 | +// +--------------------------+-------------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "frames": [ + { + "schema": { + "name": "ordering frame", + "fields": [ + { + "name": "name", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "score", + "type": "number", + "typeInfo": { + "frame": "float64" + } + } + ] + }, + "data": { + "values": [ + [ + "Loki 2.0", + "Loki 20.0", + "Loki Stats", + "Loki 2.0 Stats", + "Loki histogram", + "Loki histogram2", + "Loki Second Word", + "Loki Tests - Bar Gauge 2" + ], + [ + 8.386497572003142, + 8.351238737232393, + 8.289644692681875, + 8.237634633059454, + 8.237634633059454, + 8.214550743132483, + 8.173207674966303, + 8.105690026892566 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/ordering-tests-6-[Loki_stats].jsonc b/pkg/services/searchV2/testdata/ordering-tests-6-[Loki_stats].jsonc new file mode 100644 index 00000000000..868233ba6c3 --- /dev/null +++ b/pkg/services/searchV2/testdata/ordering-tests-6-[Loki_stats].jsonc @@ -0,0 +1,53 @@ +// 🌟 This was machine generated. Do not edit. 🌟 +// +// Frame[0] +// Name: ordering frame +// Dimensions: 2 Fields by 2 Rows +// +----------------+-------------------+ +// | Name: name | Name: score | +// | Labels: | Labels: | +// | Type: []string | Type: []float64 | +// +----------------+-------------------+ +// | Loki Stats | 9.397899591158676 | +// | Loki 2.0 Stats | 2.638536183312778 | +// +----------------+-------------------+ +// +// +// 🌟 This was machine generated. Do not edit. 🌟 +{ + "frames": [ + { + "schema": { + "name": "ordering frame", + "fields": [ + { + "name": "name", + "type": "string", + "typeInfo": { + "frame": "string" + } + }, + { + "name": "score", + "type": "number", + "typeInfo": { + "frame": "float64" + } + } + ] + }, + "data": { + "values": [ + [ + "Loki Stats", + "Loki 2.0 Stats" + ], + [ + 9.397899591158676, + 2.638536183312778 + ] + ] + } + } + ] +} \ No newline at end of file diff --git a/pkg/services/searchV2/testdata/scattered-tokens-match-reversed.jsonc b/pkg/services/searchV2/testdata/scattered-tokens-match-reversed.jsonc index 1ce404b7751..7c1178331a3 100644 --- a/pkg/services/searchV2/testdata/scattered-tokens-match-reversed.jsonc +++ b/pkg/services/searchV2/testdata/scattered-tokens-match-reversed.jsonc @@ -3,19 +3,17 @@ // Frame[0] { // "type": "search-results", // "custom": { -// "count": 2 +// "count": 0 // } // } // 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 | 2 | A secret is powerful when it is empty (Umberto Eco) | | /pfix/d/2/ | null | [] | | -// | dashboard | 1 | Three can keep a secret, if two of them are dead (Benjamin Franklin) | | /pfix/d/1/ | null | [] | | -// +----------------+----------------+----------------------------------------------------------------------+------------------+----------------+--------------------------+-------------------------+----------------+ +// Dimensions: 8 Fields by 0 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 | +// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ +// +----------------+----------------+----------------+------------------+----------------+--------------------------+-------------------------+----------------+ // // // 🌟 This was machine generated. Do not edit. 🌟 @@ -27,7 +25,7 @@ "meta": { "type": "search-results", "custom": { - "count": 2 + "count": 0 } }, "fields": [ @@ -100,38 +98,14 @@ }, "data": { "values": [ - [ - "dashboard", - "dashboard" - ], - [ - "2", - "1" - ], - [ - "A secret is powerful when it is empty (Umberto Eco)", - "Three can keep a secret, if two of them are dead (Benjamin Franklin)" - ], - [ - "", - "" - ], - [ - "/pfix/d/2/", - "/pfix/d/1/" - ], - [ - null, - null - ], - [ - [], - [] - ], - [ - "", - "" - ] + [], + [], + [], + [], + [], + [], + [], + [] ] } } diff --git a/pkg/services/searchV2/testdata/scattered-tokens-match.jsonc b/pkg/services/searchV2/testdata/scattered-tokens-match.jsonc index 64bf3ea83e2..5293618318f 100644 --- a/pkg/services/searchV2/testdata/scattered-tokens-match.jsonc +++ b/pkg/services/searchV2/testdata/scattered-tokens-match.jsonc @@ -3,18 +3,17 @@ // Frame[0] { // "type": "search-results", // "custom": { -// "count": 2 +// "count": 1 // } // } // Name: Query results -// Dimensions: 8 Fields by 2 Rows +// 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 | Three can keep a secret, if two of them are dead (Benjamin Franklin) | | /pfix/d/1/ | null | [] | | -// | dashboard | 2 | A secret is powerful when it is empty (Umberto Eco) | | /pfix/d/2/ | null | [] | | // +----------------+----------------+----------------------------------------------------------------------+------------------+----------------+--------------------------+-------------------------+----------------+ // // @@ -27,7 +26,7 @@ "meta": { "type": "search-results", "custom": { - "count": 2 + "count": 1 } }, "fields": [ @@ -101,35 +100,27 @@ "data": { "values": [ [ - "dashboard", "dashboard" ], [ - "1", - "2" + "1" ], [ - "Three can keep a secret, if two of them are dead (Benjamin Franklin)", - "A secret is powerful when it is empty (Umberto Eco)" + "Three can keep a secret, if two of them are dead (Benjamin Franklin)" ], [ - "", "" ], [ - "/pfix/d/1/", - "/pfix/d/2/" + "/pfix/d/1/" ], [ - null, null ], [ - [], [] ], [ - "", "" ] ]