Skip to content
Binary file modified data/dump.rdb
Binary file not shown.
3 changes: 1 addition & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ version: '3.4'

services:
redis:
container_name: redismod
image: redislabs/redismod:latest
image: redis/redis-stack-server:latest
ports:
- '6379:6379'

Expand Down
3 changes: 1 addition & 2 deletions docker-compose/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ version: '3.4'

services:
redis:
container_name: redismod
image: redislabs/redismod:latest
image: redis/redis-stack-server
ports:
- '6379:6379'
volumes:
Expand Down
3 changes: 1 addition & 2 deletions docker-compose/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ version: '3.4'

services:
redis:
container_name: redismod
image: redislabs/redismod:latest
image: redis/redis-stack-server
ports:
- '6379:6379'
volumes:
Expand Down
5 changes: 2 additions & 3 deletions docker-compose/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ version: '3.4'

services:
redis:
container_name: redis-test
image: redislabs/redismod:latest
image: redis/redis-stack-server
ports:
- '63790:6379'
- '6379:6379'
volumes:
- '../data:/data/:rw'
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
"@types/enzyme": "^3.10.11",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/lodash": "4.14.178",
"@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.5"
"enzyme-adapter-react-16": "^1.15.5",
"@types/react-dom": "18.0.11",
"sinon": "^15.1.0"
},
"engines": {
"node": ">=14"
Expand Down
1 change: 1 addition & 0 deletions pkg/models/redis-search.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package models
*/
const (
SearchInfo = "ft.info"
Search = "ft.search"
)

/**
Expand Down
3 changes: 3 additions & 0 deletions pkg/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ func query(ctx context.Context, query backend.DataQuery, client redisClient, qm
case models.SearchInfo:
return queryFtInfo(qm, client)

case models.Search:
return queryFtSearch(qm, client)

/**
* Custom commands
*/
Expand Down
1 change: 1 addition & 0 deletions pkg/query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func TestQuery(t *testing.T) {
{queryModel{Command: models.ClusterInfo}},
{queryModel{Command: models.ClusterNodes}},
{queryModel{Command: models.SearchInfo}},
{queryModel{Command: models.Search}},
{queryModel{Command: models.XInfoStream}},
{queryModel{Command: models.TMScan}},
{queryModel{Command: models.GearsPyStats}},
Expand Down
176 changes: 122 additions & 54 deletions pkg/redis-search.go
Original file line number Diff line number Diff line change
@@ -1,67 +1,135 @@
package main

import (
"strconv"
"strconv"

"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/redisgrafana/grafana-redis-datasource/pkg/models"
"github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/data"
"github.com/redisgrafana/grafana-redis-datasource/pkg/models"
)

func queryFtSearch(qm queryModel, client redisClient) backend.DataResponse {
response := backend.DataResponse{}

var result interface{}
args := []string{qm.Key}
if qm.SearchQuery == "" {
args = append(args, "*")
} else {
args = append(args, qm.SearchQuery)
}

if qm.ReturnFields != nil && len(qm.ReturnFields) > 0 {
args = append(args, "RETURN")
args = append(args, strconv.Itoa(len(qm.ReturnFields)))
args = append(args, qm.ReturnFields...)
}

if qm.Count != 0 || qm.Offset > 0 {
var count int
if qm.Count == 0 {
count = 10
} else {
count = qm.Count
}
args = append(args, "LIMIT", strconv.Itoa(qm.Offset), strconv.Itoa(count))
}

if qm.SortBy != "" {
args = append(args, "SORTBY", qm.SortBy, qm.SortDirection)
}

err := client.RunCmd(&result, qm.Command, args...)

if err != nil {
return errorHandler(response, err)
}

frame := data.NewFrame("Results")
fieldValuesMap := make(map[string][]string)

fieldValuesMap["keyName"] = make([]string, len(result.([]interface{}))/2)

for i := 1; i < len(result.([]interface{})); i += 2 {
keyName := string((result.([]interface{}))[i].([]uint8))
fieldValuesMap["keyName"][i/2] = keyName
fieldValueArr := (result.([]interface{}))[i+1].([]interface{})

for j := 0; j < len(fieldValueArr); j += 2 {
fieldName := string(fieldValueArr[j].([]uint8))

if _, ok := fieldValuesMap[fieldName]; !ok {
fieldValuesMap[fieldName] = make([]string, len(result.([]interface{}))/2)
}

fieldValue := string(fieldValueArr[j+1].([]uint8))
fieldValuesMap[fieldName][i/2] = fieldValue
}
}

for fieldName, slice := range fieldValuesMap {
frame.Fields = append(frame.Fields, data.NewField(fieldName, nil, slice))
}

response.Frames = append(response.Frames, frame)

return response
}

/**
* FT.INFO {index}
*
* @see https://oss.redislabs.com/redisearch/Commands/#ftinfo
*/
func queryFtInfo(qm queryModel, client redisClient) backend.DataResponse {
response := backend.DataResponse{}

// Execute command
var result map[string]interface{}
err := client.RunCmd(&result, qm.Command, qm.Key)

// Check error
if err != nil {
return errorHandler(response, err)
}

// Create data frame response
frame := data.NewFrame(qm.Key)

// Add fields and values
for key := range result {
// Value
switch value := result[key].(type) {
case int64:
// Add field
field := data.NewField(key, nil, []int64{value})
frame.Fields = append(frame.Fields, field)
case []byte:
// Parse Float
if floatValue, err := strconv.ParseFloat(string(value), 64); err == nil {
field := data.NewField(key, nil, []float64{floatValue})

// Set unit
if models.SearchInfoConfig[key] != "" {
field.Config = &data.FieldConfig{Unit: models.SearchInfoConfig[key]}
}

frame.Fields = append(frame.Fields, field)
} else {
frame.Fields = append(frame.Fields, data.NewField(key, nil, []string{string(value)}))
}
case string:
frame.Fields = append(frame.Fields, data.NewField(key, nil, []string{string(value)}))
case []interface{}:
default:
log.DefaultLogger.Error(models.SearchInfo, "Conversion Error", "Unsupported Value type")
}
}

// Add the frame to the response
response.Frames = append(response.Frames, frame)

// Return Response
return response
response := backend.DataResponse{}

// Execute command
var result map[string]interface{}
err := client.RunCmd(&result, qm.Command, qm.Key)

// Check error
if err != nil {
return errorHandler(response, err)
}

// Create data frame response
frame := data.NewFrame(qm.Key)

// Add fields and values
for key := range result {
// Value
switch value := result[key].(type) {
case int64:
// Add field
field := data.NewField(key, nil, []int64{value})
frame.Fields = append(frame.Fields, field)
case []byte:
// Parse Float
if floatValue, err := strconv.ParseFloat(string(value), 64); err == nil {
field := data.NewField(key, nil, []float64{floatValue})

// Set unit
if models.SearchInfoConfig[key] != "" {
field.Config = &data.FieldConfig{Unit: models.SearchInfoConfig[key]}
}

frame.Fields = append(frame.Fields, field)
} else {
frame.Fields = append(frame.Fields, data.NewField(key, nil, []string{string(value)}))
}
case string:
frame.Fields = append(frame.Fields, data.NewField(key, nil, []string{string(value)}))
case []interface{}:
default:
log.DefaultLogger.Error(models.SearchInfo, "Conversion Error", "Unsupported Value type")
}
}

// Add the frame to the response
response.Frames = append(response.Frames, frame)

// Return Response
return response
}
Loading