Mongodb plugin-variable-query

Hello,
I have created a MongoDB datasource plugin, and currently, queries are being executed, and I can fetch values from the database and display them on charts and tables. However, I’m encountering an issue with variables—queries are not showing up as options in the variable selection.

Could you please guide me on how to make queries appear in the variable section? Do I need to write specific code in the plugin for this functionality?

I’ve searched online but couldn’t find relevant sources. Any advice would be greatly appreciated!

Thank you!

there are a couple of options with variables, you can use a custom variable and specify some values, for example you call your variable fruit and add some values: orange, lemon, banana

then you can use this variable in your mongo query for example: select * from sales where fruit in $fruit

or you can create a query variable called fruit with the query: select name from fruit;

this will create a variable with a list of values returned from the database: then you can use this again to query the db if you want to

Thank you for your response.
My question is regarding the absence of the query section in the variable.
I’ve shown it in the image below.
I’m not sure how this section should be added.
Please share any resources or references for creating this section with me.
Thank you.

//VariableQueryEditor.tsx

import React, { ChangeEvent } from 'react';
import { VerticalGroup, InlineField, InlineFieldRow, Input, Checkbox, TextArea, Button } from '@grafana/ui';
import { QueryEditorProps } from '@grafana/data';
import { DataSource } from '../datasource';
import { MyDataSourceOptions, MyQuery } from '../types';

type Props = QueryEditorProps<DataSource, MyQuery, MyDataSourceOptions>;

export function VariableQueryEditor({ query, onChange, onRunQuery }: Props) {
  const onVariableFieldChange = (event: ChangeEvent<HTMLInputElement>) => {
    onChange({ ...query, variableField: event.target.value });
  };

  const onQueryTextChange = (event: ChangeEvent<HTMLTextAreaElement>) => {
    onChange({ ...query, queryText: event.target.value });
  };

  const onIsVariableChange = (event: ChangeEvent<HTMLInputElement>) => {
    onChange({ ...query, isVariable: event.target.checked });
  };

  const { variableField, queryText, isVariable } = query;

  return (
    <div className="gf-form">
      <VerticalGroup spacing="sm">
        <InlineFieldRow>
          <InlineField label="Is Variable">
            <Checkbox onChange={onIsVariableChange} value={isVariable || false} />
          </InlineField>
        </InlineFieldRow>
        
        {isVariable && (
          <InlineFieldRow>
            <InlineField label="Variable Field">
              <Input 
                onChange={onVariableFieldChange} 
                value={variableField || ''} 
                placeholder="Field name for variable options" 
                autoComplete="off" 
              />
            </InlineField>
          </InlineFieldRow>
        )}

        <InlineFieldRow style={{ width: '100%' }}>
          <InlineField grow style={{ width: '100%' }}>
            <TextArea
              onChange={onQueryTextChange}
              value={queryText || ''} 
              placeholder="Enter a query…" 
              rows={8}
            />
          </InlineField>
        </InlineFieldRow>

        <InlineFieldRow>
          <Button variant="secondary" onClick={onRunQuery}>
            Run Query
          </Button>
        </InlineFieldRow>
      </VerticalGroup>
    </div>
  );
}


//module.ts
import { DataSourcePlugin } from '@grafana/data';
import { DataSource } from './datasource';
import { ConfigEditor } from './components/ConfigEditor';
import { QueryEditor } from './components/QueryEditor';
import { VariableQueryEditor } from './components/VariableQueryEditor';
import { MyQuery, MyDataSourceOptions } from './types';

export const plugin = new DataSourcePlugin<DataSource, MyQuery, MyDataSourceOptions>(DataSource)
  .setConfigEditor(ConfigEditor)
  .setQueryEditor(QueryEditor)
  .setVariableQueryEditor(VariableQueryEditor as any);
//datasource.go

func (d *Datasource) MetricFindQuery(ctx context.Context, query backend.DataQuery) backend.DataResponse {
    var queryData queryModel
    if err := json.Unmarshal(query.JSON, &queryData); err != nil {
        return newErrorResponse(backend.StatusBadRequest, fmt.Errorf("invalid query JSON: %v", err))
    }

    collection := d.getCollection(queryData.Database, queryData.Collection)
    if collection == nil {
        return newErrorResponse(backend.StatusBadRequest, fmt.Errorf("invalid collection"))
    }

    pipeline := mongo.Pipeline{
        bson.D{
            {Key: "$group", Value: bson.D{
                {Key: "_id", Value: "$" + queryData.VariableField},
            }},
        },
    }

    cursor, err := collection.Aggregate(ctx, pipeline)
    if err != nil {
        log.DefaultLogger.Error("Error executing aggregation:", err)
        return newErrorResponse(backend.StatusBadRequest, err)
    }
    defer cursor.Close(ctx)

    var results []string
    for cursor.Next(ctx) {
        var result struct {
            ID string `bson:"_id"`
        }
        if err := cursor.Decode(&result); err != nil {
            log.DefaultLogger.Error("Decode error:", err)
            continue
        }
        results = append(results, result.ID)
    }

    return createVariableResponse(results)
}

Grafana" version=10.0.3