Call Elasticsearch queries from Custom Kibana Plugin

Good day, I have searched high and low for an example that works in 2021 (ES 7.11) on how to implement ES querying from a Custom Kibana Plugin. The use case is there are config files stored in an index that we would like to CRUD to via a custom plugin. I have seen that elasticsearch-js shouldn't/can't be used client side and there seems to be no other documentation on how to go about this.

So far I have a test plugin that works with their example like so:

const onClickHandler = () => {
    indent preformatted text by 4 spaces
    // Use the core http service to make a response to the server API.

    http.get('/api/test_plugin/example').then((res) => {

      console.log(res);

      setTimestamp(res.time);

      // Use the core notifications service to display a success message.

      notifications.toasts.addSuccess(

        i18n.translate('testPlugin.dataUpdated', {

          defaultMessage: 'Data updated',

        })

      );

    });

  };

However, I do not know how to access the indices from my ReactJS based plugin. If there is any documentation or package I am not aware of, please let me know. Many previous questions had dead links or redirected to outdated documentation.

On the server side of your plugin (where you implement your route /api/test_plugin/example), you can get access to an ES client via context.core.elasticsearch.client.asCurrentUser to do ES queries, then pass the results to the client.

This is an example in the Lens plugin: kibana/field_stats.ts at ee84e0b0b709d01c08ae42daa08b20c197f7b2a7 · elastic/kibana · GitHub

I'm building something similar right now for educational purposes.

There are multiple ways to achieve this but I chose to use Axios due to familiarity. On your client side you want to access your server side route by doing something like.

            axios({
                method: "post",
                url: "/api/crud/get_table_data",
                data: bodyFormData,
                headers: { "Content-Type": "application/json", "kbn-xsrf": "true" },
            })
                .then(function (response) {
                    tableDataSet(response.data.reply);
                });

Then on the server side it's what @flash1293 linked to but here is a smaller example and probably pretty close to what you want to do.

import { IRouter } from '../../../../src/core/server';
import { schema } from '@kbn/config-schema';

export function registerGetTableDataRoute(router: IRouter) {
    router.post(
        {
            path: '/api/crud/get_table_data',
            validate: {
                body: schema.object({
                    selectedIndex: schema.string(),
                    selectedFields: schema.string(),
                }),
            },
        },
        async (context, request, response) => {

            const client = context.core.elasticsearch.client.asCurrentUser;

            const { body: result } = await client.search({
                index: request.body.selectedIndex,
                _source_includes: request.body.selectedFields,
                version: true,
                size: 10000
            });

            const reply = result.hits.hits;

            return response.ok({
                body: {
                    reply,
                },
            });
        }
    );
}

Thanks for the reduced example, @aaron-nimocks . It's possible to use axios, the recommended way is to use the core http service (as you seem to do already in your original post). So if you start from scratch now, it makes sense to stick with that (it will take care of xsrf protection and the like automatically)

1 Like

Thank you for the quick replies. I'm very new to ES and some of these examples are going over my head :sweat_smile:

Maybe installing my plugin and seeing how it works will help since it's doing something similar. Just want to make clear that this is not even close to being finished and wasn't meant for human consumption. :slight_smile:

It's just a project I am using to help learn everything, same as you are doing. This one allows you to select any index pattern, then select the fields you want to view, and then finally goes get's the data to fill a table. The pre-search filters and any edit functionality has not been added yet.

Hopefully this will help with your learning curve.

1 Like

Thank you so much! This seems to have worked for me :slight_smile: posting here for others

function queryElasticSearch() {
    // registerGetTableDataRoute(CoreSetup);
    axios({
      method: 'post',
      url: `/api/console/proxy?path=_cat/indices&method=GET`,
      headers: { 'kbn-xsrf': 'kibana' }
    }).then((response) => {
      console.log(response);
    }).catch(function (error) {
      console.log(error);
    });;
  }

That might work, however make sure to check each minor version upgrade whether it still works. The console API is not considered public AFAIK so we don't make any effort to keep it backwards compatible.

1 Like

There is an example in that plug-in called get_index_list.ts I believe and would look at swapping to that when you start getting comfortable with the code.