Python ElasticSearch programming

ElasticSearch connections, indexing, searching, aggregations and TLS from Python services.

Create an outgoing ElasticSearch connection in Dashboard and everything that ElasticSearch offers will be available to your services via the underlying elasticsearch library, as in the examples below.

Creating a connection

In Dashboard, go to Connections -> Outgoing -> ElasticSearch and click Create a new outgoing ElasticSearch connection.

Fill in the form:

  • Name - any name of your choice
  • Addresses - one full http(s)://host:port URL per line, e.g. a single https://localhost:9200 line or several lines when connecting to a cluster - the scheme of each URL decides whether TLS is used
  • Username and password - credentials to authenticate with, leave them empty if the server does not require authentication
  • Timeout - how many seconds to wait for a response to a single request

The TLS section lets you connect to servers that require encrypted connections - point the CA certificates file to the PEM certificate of the authority that signed the server's certificate. For mutual TLS, add a combined client certificate and private key PEM file too. The validation checkbox can be turned off with test environments whose certificates cannot be verified.

After the connection is created, click Ping to confirm that Zato can reach the server.

Indexing documents

In your services, look up the connection by name with self.es - what you get back is an ElasticSearch client, so indices and documents are accessed the way the client does it.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class MyService(Service):

    def handle(self):

        # Get a client by the connection's name
        conn = self.es['My ElasticSearch Connection']

        # Index a document under an ID of our choice
        result = conn.index(index='orders', id='order-123', document={'order_id': 123, 'status': 'ready'})

        self.logger.info('Indexed: %s', result['result'])

Searching

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class MyService(Service):

    def handle(self):
        conn = self.es['My ElasticSearch Connection']

        # Get one document by its ID
        order = conn.get(index='orders', id='order-123')
        self.logger.info('Order: %s', order['_source'])

        # Find all documents matching a query
        result = conn.search(index='orders', query={'match': {'status': 'ready'}})

        for item in result['hits']['hits']:
            self.logger.info('Ready: %s', item['_source'])

Updating and deleting

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class MyService(Service):

    def handle(self):
        conn = self.es['My ElasticSearch Connection']

        # Update a document
        conn.update(index='orders', id='order-123', doc={'status': 'shipped'})

        # Delete a document
        conn.delete(index='orders', id='order-123')

Aggregations

The full aggregations framework is available too.

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class MyService(Service):

    def handle(self):
        conn = self.es['My ElasticSearch Connection']

        # Count orders per status
        aggregations = {
            'per_status': {
                'terms': {'field': 'status.keyword'}
            }
        }

        result = conn.search(index='orders', size=0, aggregations=aggregations)

        for bucket in result['aggregations']['per_status']['buckets']:
            self.logger.info('%s: %s', bucket['key'], bucket['doc_count'])

Pinging from a service

# -*- coding: utf-8 -*-

# Zato
from zato.server.service import Service

class MyService(Service):

    def handle(self):
        conn = self.es['My ElasticSearch Connection']

        # The same request that the Dashboard's Ping link makes
        conn.info()

        self.logger.info('ElasticSearch is reachable')

Testing with a local server

To test your connections without an existing ElasticSearch installation, one command starts a complete server in Docker:

docker run -d --rm --name zato-elasticsearch -e discovery.type=single-node -e xpack.security.enabled=false -p 9200:9200 docker.elastic.co/elasticsearch/elasticsearch:9.0.0

In Dashboard, create an outgoing ElasticSearch connection with http://localhost:9200 in the addresses field, leave the username and password empty, and click Ping to confirm that Zato can reach the server.

When you are done, the container removes itself on stop:

docker stop zato-elasticsearch

Also of interest

Learn more