2025-04-01 10:38:02 +09:00

138 lines
3.7 KiB
Go

package dashboardsearch
import (
"encoding/binary"
"encoding/json"
"fmt"
common "github.com/grafana/grafana/pkg/apimachinery/apis/common/v0alpha1"
"github.com/grafana/grafana/pkg/apis/dashboard/v0alpha1"
"github.com/grafana/grafana/pkg/storage/unified/resource"
)
var (
excludedFields = map[string]string{
resource.SEARCH_FIELD_EXPLAIN: "",
resource.SEARCH_FIELD_SCORE: "",
resource.SEARCH_FIELD_TITLE: "",
resource.SEARCH_FIELD_FOLDER: "",
resource.SEARCH_FIELD_TAGS: "",
}
IncludeFields = []string{
resource.SEARCH_FIELD_TITLE,
resource.SEARCH_FIELD_TAGS,
resource.SEARCH_FIELD_LABELS,
resource.SEARCH_FIELD_FOLDER,
resource.SEARCH_FIELD_CREATED,
resource.SEARCH_FIELD_CREATED_BY,
resource.SEARCH_FIELD_UPDATED,
resource.SEARCH_FIELD_UPDATED_BY,
resource.SEARCH_FIELD_MANAGER_KIND,
resource.SEARCH_FIELD_MANAGER_ID,
resource.SEARCH_FIELD_SOURCE_PATH,
resource.SEARCH_FIELD_SOURCE_CHECKSUM,
resource.SEARCH_FIELD_SOURCE_TIME,
}
)
func ParseResults(result *resource.ResourceSearchResponse, offset int64) (v0alpha1.SearchResults, error) {
if result == nil {
return v0alpha1.SearchResults{}, nil
} else if result.Error != nil {
return v0alpha1.SearchResults{}, fmt.Errorf("%d error searching: %s: %s", result.Error.Code, result.Error.Message, result.Error.Details)
} else if result.Results == nil {
return v0alpha1.SearchResults{}, nil
}
titleIDX := 0
folderIDX := -1
tagsIDX := -1
scoreIDX := 0
explainIDX := 0
for i, v := range result.Results.Columns {
switch v.Name {
case resource.SEARCH_FIELD_EXPLAIN:
explainIDX = i
case resource.SEARCH_FIELD_SCORE:
scoreIDX = i
case resource.SEARCH_FIELD_TITLE:
titleIDX = i
case resource.SEARCH_FIELD_FOLDER:
folderIDX = i
case resource.SEARCH_FIELD_TAGS:
tagsIDX = i
}
}
sr := v0alpha1.SearchResults{
Offset: offset,
TotalHits: result.TotalHits,
QueryCost: result.QueryCost,
MaxScore: result.MaxScore,
Hits: make([]v0alpha1.DashboardHit, len(result.Results.Rows)),
}
for i, row := range result.Results.Rows {
fields := &common.Unstructured{}
for colIndex, col := range result.Results.Columns {
if _, ok := excludedFields[col.Name]; !ok {
val, err := resource.DecodeCell(col, colIndex, row.Cells[colIndex])
if err != nil {
return v0alpha1.SearchResults{}, err
}
// Some of the dashboard fields come in as int32, but we need to convert them to int64 or else fields.Set() will panic
int32Val, ok := val.(int32)
if ok {
val = int64(int32Val)
}
fields.Set(col.Name, val)
}
}
hit := &v0alpha1.DashboardHit{
Resource: row.Key.Resource, // folders | dashboards
Name: row.Key.Name, // The Grafana UID
Title: string(row.Cells[titleIDX]),
Field: fields,
}
if folderIDX > 0 && row.Cells[folderIDX] != nil {
hit.Folder = string(row.Cells[folderIDX])
}
if tagsIDX > 0 && row.Cells[tagsIDX] != nil {
_ = json.Unmarshal(row.Cells[tagsIDX], &hit.Tags)
}
if explainIDX > 0 && row.Cells[explainIDX] != nil {
_ = json.Unmarshal(row.Cells[explainIDX], &hit.Explain)
}
if scoreIDX > 0 && row.Cells[scoreIDX] != nil {
_, _ = binary.Decode(row.Cells[scoreIDX], binary.BigEndian, &hit.Score)
}
sr.Hits[i] = *hit
}
// Add facet results
if result.Facet != nil {
sr.Facets = make(map[string]v0alpha1.FacetResult)
for k, v := range result.Facet {
sr.Facets[k] = v0alpha1.FacetResult{
Field: v.Field,
Total: v.Total,
Missing: v.Missing,
Terms: make([]v0alpha1.TermFacet, len(v.Terms)),
}
for j, t := range v.Terms {
sr.Facets[k].Terms[j] = v0alpha1.TermFacet{
Term: t.Term,
Count: t.Count,
}
}
}
}
return sr, nil
}