mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Search: Add DashboardIndexExtender interface (#49045)
Co-authored-by: Alexander Emelin <frvzmb@gmail.com>
This commit is contained in:
parent
6bb843bd0e
commit
f0f33733a5
@ -35,7 +35,7 @@ const (
|
||||
documentFieldInternalID = "__internal_id" // only for migrations! (indexed as a string)
|
||||
)
|
||||
|
||||
func initIndex(dashboards []dashboard, logger log.Logger) (*bluge.Reader, *bluge.Writer, error) {
|
||||
func initIndex(dashboards []dashboard, logger log.Logger, extendDoc ExtendDashboardFunc) (*bluge.Reader, *bluge.Writer, error) {
|
||||
writer, err := bluge.OpenWriter(bluge.InMemoryOnlyConfig())
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error opening writer: %v", err)
|
||||
@ -74,6 +74,9 @@ func initIndex(dashboards []dashboard, logger log.Logger) (*bluge.Reader, *bluge
|
||||
continue
|
||||
}
|
||||
doc := getFolderDashboardDoc(dash)
|
||||
if err := extendDoc(dash.uid, doc); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
batch.Insert(doc)
|
||||
if err := flushIfRequired(false); err != nil {
|
||||
return nil, nil, err
|
||||
@ -93,6 +96,9 @@ func initIndex(dashboards []dashboard, logger log.Logger) (*bluge.Reader, *bluge
|
||||
folderUID := folderIdLookup[dash.folderID]
|
||||
location := folderUID
|
||||
doc := getNonFolderDashboardDoc(dash, location)
|
||||
if err := extendDoc(dash.uid, doc); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
batch.Insert(doc)
|
||||
if err := flushIfRequired(false); err != nil {
|
||||
return nil, nil, err
|
||||
@ -186,8 +192,6 @@ func getNonFolderDashboardDoc(dash dashboard, location string) *bluge.Document {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: enterprise, add dashboard sorting fields
|
||||
|
||||
return doc
|
||||
}
|
||||
|
||||
@ -313,7 +317,7 @@ func getDashboardPanelIDs(reader *bluge.Reader, dashboardUID string) ([]string,
|
||||
}
|
||||
|
||||
//nolint: gocyclo
|
||||
func doSearchQuery(ctx context.Context, logger log.Logger, reader *bluge.Reader, filter ResourceFilter, q DashboardQuery) *backend.DataResponse {
|
||||
func doSearchQuery(ctx context.Context, logger log.Logger, reader *bluge.Reader, filter ResourceFilter, q DashboardQuery, extender QueryExtender) *backend.DataResponse {
|
||||
response := &backend.DataResponse{}
|
||||
|
||||
// Folder listing structure
|
||||
@ -419,8 +423,10 @@ func doSearchQuery(ctx context.Context, logger log.Logger, reader *bluge.Reader,
|
||||
}
|
||||
req.WithStandardAggregations()
|
||||
|
||||
// SortBy([]string{"-_score", "name"})
|
||||
// req.SortBy([]string{documentFieldName})
|
||||
// Field must be .Sortable() for sort to work with it.
|
||||
if q.Sort != "" {
|
||||
req.SortBy([]string{q.Sort})
|
||||
}
|
||||
|
||||
for _, t := range q.Facet {
|
||||
lim := t.Limit
|
||||
@ -475,6 +481,9 @@ func doSearchQuery(ctx context.Context, logger log.Logger, reader *bluge.Reader,
|
||||
frame.Fields = append(frame.Fields, fScore, fExplain)
|
||||
}
|
||||
|
||||
fieldLen := 0
|
||||
ext := extender.GetFramer(frame)
|
||||
|
||||
locationItems := make(map[string]bool, 50)
|
||||
|
||||
// iterate through the document matches
|
||||
@ -521,6 +530,8 @@ func doSearchQuery(ctx context.Context, logger log.Logger, reader *bluge.Reader,
|
||||
ds_uids = append(ds_uids, string(value))
|
||||
case documentFieldTag:
|
||||
tags = append(tags, string(value))
|
||||
default:
|
||||
return ext(field, value)
|
||||
}
|
||||
return true
|
||||
})
|
||||
@ -571,6 +582,14 @@ func doSearchQuery(ctx context.Context, logger log.Logger, reader *bluge.Reader,
|
||||
}
|
||||
}
|
||||
|
||||
// extend fields to match the longest field
|
||||
fieldLen++
|
||||
for _, f := range frame.Fields {
|
||||
if fieldLen > f.Len() {
|
||||
f.Extend(fieldLen - f.Len())
|
||||
}
|
||||
}
|
||||
|
||||
// load the next document match
|
||||
match, err = documentMatchIterator.Next()
|
||||
}
|
||||
|
48
pkg/services/searchV2/extender.go
Normal file
48
pkg/services/searchV2/extender.go
Normal file
@ -0,0 +1,48 @@
|
||||
package searchV2
|
||||
|
||||
import (
|
||||
"github.com/blugelabs/bluge"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
)
|
||||
|
||||
type ExtendDashboardFunc func(uid string, doc *bluge.Document) error
|
||||
type FramerFunc func(field string, value []byte) bool
|
||||
|
||||
type QueryExtender interface {
|
||||
GetFramer(frame *data.Frame) FramerFunc
|
||||
}
|
||||
|
||||
type DocumentExtender interface {
|
||||
GetDashboardExtender(orgID int64, uids ...string) ExtendDashboardFunc
|
||||
}
|
||||
|
||||
type DashboardIndexExtender interface {
|
||||
GetDocumentExtender() DocumentExtender
|
||||
GetQueryExtender() QueryExtender
|
||||
}
|
||||
|
||||
type NoopExtender struct{}
|
||||
|
||||
func (n NoopExtender) GetDocumentExtender() DocumentExtender {
|
||||
return &NoopDocumentExtender{}
|
||||
}
|
||||
|
||||
func (n NoopExtender) GetQueryExtender() QueryExtender {
|
||||
return &NoopQueryExtender{}
|
||||
}
|
||||
|
||||
type NoopDocumentExtender struct{}
|
||||
|
||||
func (n NoopDocumentExtender) GetDashboardExtender(_ int64, _ ...string) ExtendDashboardFunc {
|
||||
return func(uid string, doc *bluge.Document) error {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type NoopQueryExtender struct{}
|
||||
|
||||
func (n NoopQueryExtender) GetFramer(_ *data.Frame) FramerFunc {
|
||||
return func(field string, value []byte) bool {
|
||||
return true
|
||||
}
|
||||
}
|
@ -53,9 +53,10 @@ type dashboardIndex struct {
|
||||
eventStore eventStore
|
||||
logger log.Logger
|
||||
buildSignals chan int64
|
||||
extender DocumentExtender
|
||||
}
|
||||
|
||||
func newDashboardIndex(dashLoader dashboardLoader, evStore eventStore) *dashboardIndex {
|
||||
func newDashboardIndex(dashLoader dashboardLoader, evStore eventStore, extender DocumentExtender) *dashboardIndex {
|
||||
return &dashboardIndex{
|
||||
loader: dashLoader,
|
||||
eventStore: evStore,
|
||||
@ -63,6 +64,7 @@ func newDashboardIndex(dashLoader dashboardLoader, evStore eventStore) *dashboar
|
||||
perOrgWriter: map[int64]*bluge.Writer{},
|
||||
logger: log.New("dashboardIndex"),
|
||||
buildSignals: make(chan int64),
|
||||
extender: extender,
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +213,8 @@ func (i *dashboardIndex) buildOrgIndex(ctx context.Context, orgID int64) (int, e
|
||||
orgSearchIndexLoadTime := time.Since(started)
|
||||
i.logger.Info("Finish loading org dashboards", "elapsed", orgSearchIndexLoadTime, "orgId", orgID)
|
||||
|
||||
reader, writer, err := initIndex(dashboards, i.logger)
|
||||
dashboardExtender := i.extender.GetDashboardExtender(orgID)
|
||||
reader, writer, err := initIndex(dashboards, i.logger, dashboardExtender)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("error initializing index: %w", err)
|
||||
}
|
||||
@ -350,7 +353,7 @@ func (i *dashboardIndex) applyDashboardEvent(ctx context.Context, orgID int64, d
|
||||
if len(dbDashboards) == 0 {
|
||||
newReader, err = i.removeDashboard(writer, reader, dashboardUID)
|
||||
} else {
|
||||
newReader, err = i.updateDashboard(writer, reader, dbDashboards[0])
|
||||
newReader, err = i.updateDashboard(orgID, writer, reader, dbDashboards[0])
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
@ -389,12 +392,17 @@ func stringInSlice(str string, slice []string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (i *dashboardIndex) updateDashboard(writer *bluge.Writer, reader *bluge.Reader, dash dashboard) (*bluge.Reader, error) {
|
||||
func (i *dashboardIndex) updateDashboard(orgID int64, writer *bluge.Writer, reader *bluge.Reader, dash dashboard) (*bluge.Reader, error) {
|
||||
batch := bluge.NewBatch()
|
||||
|
||||
extendDoc := i.extender.GetDashboardExtender(orgID, dash.uid)
|
||||
|
||||
var doc *bluge.Document
|
||||
if dash.isFolder {
|
||||
doc = getFolderDashboardDoc(dash)
|
||||
if err := extendDoc(dash.uid, doc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
var folderUID string
|
||||
if dash.folderID == 0 {
|
||||
@ -409,6 +417,9 @@ func (i *dashboardIndex) updateDashboard(writer *bluge.Writer, reader *bluge.Rea
|
||||
|
||||
location := folderUID
|
||||
doc = getNonFolderDashboardDoc(dash, location)
|
||||
if err := extendDoc(dash.uid, doc); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var actualPanelIDs []string
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
|
||||
"github.com/blugelabs/bluge"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/experimental"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@ -33,28 +34,40 @@ var testDisallowAllFilter = func(uid string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var testOrgID int64 = 1
|
||||
|
||||
var update = flag.Bool("update", false, "update golden files")
|
||||
|
||||
func initTestIndexFromDashes(t *testing.T, dashboards []dashboard) (*dashboardIndex, *bluge.Reader, *bluge.Writer) {
|
||||
t.Helper()
|
||||
return initTestIndexFromDashesExtended(t, dashboards, &NoopDocumentExtender{})
|
||||
}
|
||||
|
||||
func initTestIndexFromDashesExtended(t *testing.T, dashboards []dashboard, extender DocumentExtender) (*dashboardIndex, *bluge.Reader, *bluge.Writer) {
|
||||
t.Helper()
|
||||
dashboardLoader := &testDashboardLoader{
|
||||
dashboards: dashboards,
|
||||
}
|
||||
index := newDashboardIndex(dashboardLoader, &store.MockEntityEventsService{})
|
||||
index := newDashboardIndex(dashboardLoader, &store.MockEntityEventsService{}, extender)
|
||||
require.NotNil(t, index)
|
||||
numDashboards, err := index.buildOrgIndex(context.Background(), 1)
|
||||
numDashboards, err := index.buildOrgIndex(context.Background(), testOrgID)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(dashboardLoader.dashboards), numDashboards)
|
||||
reader, ok := index.getOrgReader(1)
|
||||
reader, ok := index.getOrgReader(testOrgID)
|
||||
require.True(t, ok)
|
||||
writer, ok := index.getOrgWriter(1)
|
||||
writer, ok := index.getOrgWriter(testOrgID)
|
||||
require.True(t, ok)
|
||||
return index, reader, writer
|
||||
}
|
||||
|
||||
func checkSearchResponse(t *testing.T, fileName string, reader *bluge.Reader, filter ResourceFilter, query DashboardQuery) {
|
||||
t.Helper()
|
||||
resp := doSearchQuery(context.Background(), testLogger, reader, filter, query)
|
||||
checkSearchResponseExtended(t, fileName, reader, filter, query, &NoopQueryExtender{})
|
||||
}
|
||||
|
||||
func checkSearchResponseExtended(t *testing.T, fileName string, reader *bluge.Reader, filter ResourceFilter, query DashboardQuery, extender QueryExtender) {
|
||||
t.Helper()
|
||||
resp := doSearchQuery(context.Background(), testLogger, reader, filter, query, extender)
|
||||
goldenFile := filepath.Join("testdata", fileName)
|
||||
err := experimental.CheckGoldenDataResponse(goldenFile, resp, *update)
|
||||
require.NoError(t, err)
|
||||
@ -108,7 +121,7 @@ func TestDashboardIndexUpdates(t *testing.T) {
|
||||
t.Run("dashboard-create", func(t *testing.T) {
|
||||
index, reader, writer := initTestIndexFromDashes(t, testDashboards)
|
||||
|
||||
newReader, err := index.updateDashboard(writer, reader, dashboard{
|
||||
newReader, err := index.updateDashboard(testOrgID, writer, reader, dashboard{
|
||||
id: 3,
|
||||
uid: "3",
|
||||
info: &extract.DashboardInfo{
|
||||
@ -125,7 +138,7 @@ func TestDashboardIndexUpdates(t *testing.T) {
|
||||
t.Run("dashboard-update", func(t *testing.T) {
|
||||
index, reader, writer := initTestIndexFromDashes(t, testDashboards)
|
||||
|
||||
newReader, err := index.updateDashboard(writer, reader, dashboard{
|
||||
newReader, err := index.updateDashboard(testOrgID, writer, reader, dashboard{
|
||||
id: 2,
|
||||
uid: "2",
|
||||
info: &extract.DashboardInfo{
|
||||
@ -140,6 +153,98 @@ func TestDashboardIndexUpdates(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
var testSortDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
uid: "1",
|
||||
info: &extract.DashboardInfo{
|
||||
Title: "a-test",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
uid: "2",
|
||||
info: &extract.DashboardInfo{
|
||||
Title: "z-test",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type testExtender struct {
|
||||
documentExtender DocumentExtender
|
||||
queryExtender QueryExtender
|
||||
}
|
||||
|
||||
func (t *testExtender) GetDocumentExtender() DocumentExtender {
|
||||
return t.documentExtender
|
||||
}
|
||||
|
||||
func (t *testExtender) GetQueryExtender() QueryExtender {
|
||||
return t.queryExtender
|
||||
}
|
||||
|
||||
type testDocumentExtender struct {
|
||||
ExtendDashboardFunc ExtendDashboardFunc
|
||||
}
|
||||
|
||||
func (t *testDocumentExtender) GetDashboardExtender(_ int64, _ ...string) ExtendDashboardFunc {
|
||||
return t.ExtendDashboardFunc
|
||||
}
|
||||
|
||||
type testQueryExtender struct {
|
||||
getFramer func(frame *data.Frame) FramerFunc
|
||||
}
|
||||
|
||||
func (t *testQueryExtender) GetFramer(frame *data.Frame) FramerFunc {
|
||||
return t.getFramer(frame)
|
||||
}
|
||||
|
||||
func TestDashboardIndexSort(t *testing.T) {
|
||||
var i float64
|
||||
extender := &testExtender{
|
||||
documentExtender: &testDocumentExtender{
|
||||
ExtendDashboardFunc: func(uid string, doc *bluge.Document) error {
|
||||
doc.AddField(bluge.NewNumericField("test", i).StoreValue().Sortable())
|
||||
i++
|
||||
return nil
|
||||
},
|
||||
},
|
||||
queryExtender: &testQueryExtender{
|
||||
getFramer: func(frame *data.Frame) FramerFunc {
|
||||
testNum := data.NewFieldFromFieldType(data.FieldTypeFloat64, 0)
|
||||
testNum.Name = "test num"
|
||||
frame.Fields = append(
|
||||
frame.Fields,
|
||||
testNum,
|
||||
)
|
||||
return func(field string, value []byte) bool {
|
||||
if field == "test" {
|
||||
if num, err := bluge.DecodeNumericFloat64(value); err == nil {
|
||||
testNum.Append(num)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("sort-asc", func(t *testing.T) {
|
||||
_, reader, _ := initTestIndexFromDashesExtended(t, testSortDashboards, extender.GetDocumentExtender())
|
||||
checkSearchResponseExtended(t, filepath.Base(t.Name())+".txt", reader, testAllowAllFilter,
|
||||
DashboardQuery{Query: "*", Sort: "test"}, extender.GetQueryExtender(),
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("sort-desc", func(t *testing.T) {
|
||||
_, reader, _ := initTestIndexFromDashesExtended(t, testSortDashboards, extender.GetDocumentExtender())
|
||||
checkSearchResponseExtended(t, filepath.Base(t.Name())+".txt", reader, testAllowAllFilter,
|
||||
DashboardQuery{Query: "*", Sort: "-test"}, extender.GetQueryExtender(),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
var testPrefixDashboards = []dashboard{
|
||||
{
|
||||
id: 1,
|
||||
|
@ -26,10 +26,12 @@ type StandardSearchService struct {
|
||||
|
||||
logger log.Logger
|
||||
dashboardIndex *dashboardIndex
|
||||
extender DashboardIndexExtender
|
||||
}
|
||||
|
||||
func ProvideService(cfg *setting.Cfg, sql *sqlstore.SQLStore, entityEventStore store.EntityEventsService, ac accesscontrol.AccessControl) SearchService {
|
||||
return &StandardSearchService{
|
||||
extender := &NoopExtender{}
|
||||
s := &StandardSearchService{
|
||||
cfg: cfg,
|
||||
sql: sql,
|
||||
ac: ac,
|
||||
@ -37,9 +39,11 @@ func ProvideService(cfg *setting.Cfg, sql *sqlstore.SQLStore, entityEventStore s
|
||||
sql: sql,
|
||||
ac: ac,
|
||||
},
|
||||
dashboardIndex: newDashboardIndex(newSQLDashboardLoader(sql), entityEventStore),
|
||||
dashboardIndex: newDashboardIndex(newSQLDashboardLoader(sql), entityEventStore, extender.GetDocumentExtender()),
|
||||
logger: log.New("searchV2"),
|
||||
extender: extender,
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *StandardSearchService) IsDisabled() bool {
|
||||
@ -53,6 +57,11 @@ func (s *StandardSearchService) Run(ctx context.Context) error {
|
||||
return s.dashboardIndex.run(ctx)
|
||||
}
|
||||
|
||||
func (s *StandardSearchService) RegisterDashboardIndexExtender(ext DashboardIndexExtender) {
|
||||
s.extender = ext
|
||||
s.dashboardIndex.extender = ext.GetDocumentExtender()
|
||||
}
|
||||
|
||||
func (s *StandardSearchService) getUser(ctx context.Context, backendUser *backend.User, orgId int64) (*models.SignedInUser, error) {
|
||||
// TODO: get user & user's permissions from the request context
|
||||
|
||||
@ -123,5 +132,5 @@ func (s *StandardSearchService) DoDashboardQuery(ctx context.Context, user *back
|
||||
return rsp
|
||||
}
|
||||
|
||||
return doSearchQuery(ctx, s.logger, reader, filter, q)
|
||||
return doSearchQuery(ctx, s.logger, reader, filter, q, s.extender.GetQueryExtender())
|
||||
}
|
||||
|
@ -29,6 +29,10 @@ func (s *stubSearchService) DoDashboardQuery(ctx context.Context, user *backend.
|
||||
return rsp
|
||||
}
|
||||
|
||||
func (s *stubSearchService) RegisterDashboardIndexExtender(ext DashboardIndexExtender) {
|
||||
// noop
|
||||
}
|
||||
|
||||
func (s *stubSearchService) Run(_ context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
22
pkg/services/searchV2/testdata/sort-asc.txt
vendored
Normal file
22
pkg/services/searchV2/testdata/sort-asc.txt
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
🌟 This was machine generated. Do not edit. 🌟
|
||||
|
||||
Frame[0] {
|
||||
"type": "search-results",
|
||||
"custom": {
|
||||
"count": 2
|
||||
}
|
||||
}
|
||||
Name: Query results
|
||||
Dimensions: 9 Fields by 2 Rows
|
||||
+----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+-----------------+
|
||||
| Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: test num |
|
||||
| Labels: | 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 | Type: []float64 |
|
||||
+----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+-----------------+
|
||||
| dashboard | 1 | a-test | | /d/1/ | null | null | | 0 |
|
||||
| dashboard | 2 | z-test | | /d/2/ | null | null | | 1 |
|
||||
+----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+-----------------+
|
||||
|
||||
|
||||
====== TEST DATA RESPONSE (arrow base64) ======
|
||||
FRAME=QVJST1cxAAD/////wAQAABAAAAAAAAoADgAMAAsABAAKAAAAFAAAAAAAAAEEAAoADAAAAAgABAAKAAAACAAAAKwAAAADAAAAWAAAACgAAAAEAAAAzPv//wgAAAAMAAAAAAAAAAAAAAAFAAAAcmVmSWQAAADs+///CAAAABgAAAANAAAAUXVlcnkgcmVzdWx0cwAAAAQAAABuYW1lAAAAABj8//8IAAAAOAAAAC4AAAB7InR5cGUiOiJzZWFyY2gtcmVzdWx0cyIsImN1c3RvbSI6eyJjb3VudCI6Mn19AAAEAAAAbWV0YQAAAAAJAAAAeAMAABADAAC0AgAAUAIAAKQBAABIAQAA2AAAAHQAAAAEAAAAvvz//xQAAABAAAAASAAAAAAAAANIAAAAAQAAAAQAAACs/P//CAAAABQAAAAIAAAAdGVzdCBudW0AAAAABAAAAG5hbWUAAAAAAAAAAAAABgAIAAYABgAAAAAAAgAIAAAAdGVzdCBudW0AAAAAKv3//xQAAABAAAAAQAAAAAAAAAU8AAAAAQAAAAQAAAAY/f//CAAAABQAAAAIAAAAbG9jYXRpb24AAAAABAAAAG5hbWUAAAAAAAAAABT9//8IAAAAbG9jYXRpb24AAAAApv///xQAAAA8AAAAPAAAAAAABAE4AAAAAQAAAAQAAAB4/f//CAAAABAAAAAGAAAAZHNfdWlkAAAEAAAAbmFtZQAAAAAAAAAAcP3//wYAAABkc191aWQAAAAAEgAYABQAEwASAAwAAAAIAAQAEgAAABQAAAA8AAAAPAAAAAAABAE4AAAAAQAAAAQAAADk/f//CAAAABAAAAAEAAAAdGFncwAAAAAEAAAAbmFtZQAAAAAAAAAA3P3//wQAAAB0YWdzAAAAAE7+//8UAAAAkAAAAJAAAAAAAAAFjAAAAAIAAAAoAAAABAAAAED+//8IAAAADAAAAAMAAAB1cmwABAAAAG5hbWUAAAAAYP7//wgAAABAAAAANAAAAHsibGlua3MiOlt7InRpdGxlIjoibGluayIsInVybCI6IiR7X192YWx1ZS50ZXh0fSJ9XX0AAAAABgAAAGNvbmZpZwAAAAAAAIj+//8DAAAAdXJsAPb+//8UAAAAQAAAAEAAAAAAAAAFPAAAAAEAAAAEAAAA5P7//wgAAAAUAAAACgAAAHBhbmVsX3R5cGUAAAQAAABuYW1lAAAAAAAAAADg/v//CgAAAHBhbmVsX3R5cGUAAFb///8UAAAAPAAAADwAAAAAAAAFOAAAAAEAAAAEAAAARP///wgAAAAQAAAABAAAAG5hbWUAAAAABAAAAG5hbWUAAAAAAAAAADz///8EAAAAbmFtZQAAAACu////FAAAADgAAAA4AAAAAAAABTQAAAABAAAABAAAAJz///8IAAAADAAAAAMAAAB1aWQABAAAAG5hbWUAAAAAAAAAAJD///8DAAAAdWlkAAAAEgAYABQAAAATAAwAAAAIAAQAEgAAABQAAABEAAAASAAAAAAAAAVEAAAAAQAAAAwAAAAIAAwACAAEAAgAAAAIAAAAEAAAAAQAAABraW5kAAAAAAQAAABuYW1lAAAAAAAAAAAEAAQABAAAAAQAAABraW5kAAAAAAAAAAD/////iAIAABQAAAAAAAAADAAWABQAEwAMAAQADAAAAOAAAAAAAAAAFAAAAAAAAAMEAAoAGAAMAAgABAAKAAAAFAAAALgBAAACAAAAAAAAAAAAAAAaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAQAAAAAAAAABIAAAAAAAAAKAAAAAAAAAAAAAAAAAAAACgAAAAAAAAADAAAAAAAAAA4AAAAAAAAAAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAADAAAAAAAAABQAAAAAAAAAAwAAAAAAAAAYAAAAAAAAAAAAAAAAAAAAGAAAAAAAAAADAAAAAAAAABwAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAADAAAAAAAAACAAAAAAAAAAAoAAAAAAAAAkAAAAAAAAAABAAAAAAAAAJgAAAAAAAAADAAAAAAAAACoAAAAAAAAAAAAAAAAAAAAqAAAAAAAAAABAAAAAAAAALAAAAAAAAAADAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAADAAAAAAAAADQAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAAAAAAAAAANAAAAAAAAAAEAAAAAAAAAAAAAAACQAAAAIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAIAAAAAAAAAAgAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAJAAAAEgAAAAAAAABkYXNoYm9hcmRkYXNoYm9hcmQAAAAAAAAAAAAAAQAAAAIAAAAAAAAAMTIAAAAAAAAAAAAABgAAAAwAAAAAAAAAYS10ZXN0ei10ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAoAAAAAAAAAL2QvMS8vZC8yLwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPA/EAAAAAwAFAASAAwACAAEAAwAAAAQAAAALAAAADgAAAAAAAQAAQAAANAEAAAAAAAAkAIAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAKAAwAAAAIAAQACgAAAAgAAACsAAAAAwAAAFgAAAAoAAAABAAAAMz7//8IAAAADAAAAAAAAAAAAAAABQAAAHJlZklkAAAA7Pv//wgAAAAYAAAADQAAAFF1ZXJ5IHJlc3VsdHMAAAAEAAAAbmFtZQAAAAAY/P//CAAAADgAAAAuAAAAeyJ0eXBlIjoic2VhcmNoLXJlc3VsdHMiLCJjdXN0b20iOnsiY291bnQiOjJ9fQAABAAAAG1ldGEAAAAACQAAAHgDAAAQAwAAtAIAAFACAACkAQAASAEAANgAAAB0AAAABAAAAL78//8UAAAAQAAAAEgAAAAAAAADSAAAAAEAAAAEAAAArPz//wgAAAAUAAAACAAAAHRlc3QgbnVtAAAAAAQAAABuYW1lAAAAAAAAAAAAAAYACAAGAAYAAAAAAAIACAAAAHRlc3QgbnVtAAAAACr9//8UAAAAQAAAAEAAAAAAAAAFPAAAAAEAAAAEAAAAGP3//wgAAAAUAAAACAAAAGxvY2F0aW9uAAAAAAQAAABuYW1lAAAAAAAAAAAU/f//CAAAAGxvY2F0aW9uAAAAAKb///8UAAAAPAAAADwAAAAAAAQBOAAAAAEAAAAEAAAAeP3//wgAAAAQAAAABgAAAGRzX3VpZAAABAAAAG5hbWUAAAAAAAAAAHD9//8GAAAAZHNfdWlkAAAAABIAGAAUABMAEgAMAAAACAAEABIAAAAUAAAAPAAAADwAAAAAAAQBOAAAAAEAAAAEAAAA5P3//wgAAAAQAAAABAAAAHRhZ3MAAAAABAAAAG5hbWUAAAAAAAAAANz9//8EAAAAdGFncwAAAABO/v//FAAAAJAAAACQAAAAAAAABYwAAAACAAAAKAAAAAQAAABA/v//CAAAAAwAAAADAAAAdXJsAAQAAABuYW1lAAAAAGD+//8IAAAAQAAAADQAAAB7ImxpbmtzIjpbeyJ0aXRsZSI6ImxpbmsiLCJ1cmwiOiIke19fdmFsdWUudGV4dH0ifV19AAAAAAYAAABjb25maWcAAAAAAACI/v//AwAAAHVybAD2/v//FAAAAEAAAABAAAAAAAAABTwAAAABAAAABAAAAOT+//8IAAAAFAAAAAoAAABwYW5lbF90eXBlAAAEAAAAbmFtZQAAAAAAAAAA4P7//woAAABwYW5lbF90eXBlAABW////FAAAADwAAAA8AAAAAAAABTgAAAABAAAABAAAAET///8IAAAAEAAAAAQAAABuYW1lAAAAAAQAAABuYW1lAAAAAAAAAAA8////BAAAAG5hbWUAAAAArv///xQAAAA4AAAAOAAAAAAAAAU0AAAAAQAAAAQAAACc////CAAAAAwAAAADAAAAdWlkAAQAAABuYW1lAAAAAAAAAACQ////AwAAAHVpZAAAABIAGAAUAAAAEwAMAAAACAAEABIAAAAUAAAARAAAAEgAAAAAAAAFRAAAAAEAAAAMAAAACAAMAAgABAAIAAAACAAAABAAAAAEAAAAa2luZAAAAAAEAAAAbmFtZQAAAAAAAAAABAAEAAQAAAAEAAAAa2luZAAAAADoBAAAQVJST1cx
|
22
pkg/services/searchV2/testdata/sort-desc.txt
vendored
Normal file
22
pkg/services/searchV2/testdata/sort-desc.txt
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
🌟 This was machine generated. Do not edit. 🌟
|
||||
|
||||
Frame[0] {
|
||||
"type": "search-results",
|
||||
"custom": {
|
||||
"count": 2
|
||||
}
|
||||
}
|
||||
Name: Query results
|
||||
Dimensions: 9 Fields by 2 Rows
|
||||
+----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+-----------------+
|
||||
| Name: kind | Name: uid | Name: name | Name: panel_type | Name: url | Name: tags | Name: ds_uid | Name: location | Name: test num |
|
||||
| Labels: | 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 | Type: []float64 |
|
||||
+----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+-----------------+
|
||||
| dashboard | 2 | z-test | | /d/2/ | null | null | | 3 |
|
||||
| dashboard | 1 | a-test | | /d/1/ | null | null | | 2 |
|
||||
+----------------+----------------+----------------+------------------+----------------+--------------------------+--------------------------+----------------+-----------------+
|
||||
|
||||
|
||||
====== TEST DATA RESPONSE (arrow base64) ======
|
||||
FRAME=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
|
@ -33,4 +33,5 @@ type DashboardQuery struct {
|
||||
type SearchService interface {
|
||||
registry.BackgroundService
|
||||
DoDashboardQuery(ctx context.Context, user *backend.User, orgId int64, query DashboardQuery) *backend.DataResponse
|
||||
RegisterDashboardIndexExtender(ext DashboardIndexExtender)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user