Using Searchly with Python

Elasticsearch provides two types of clients for Python low-level and elasticsearch-dsl.

The library is compatible with all Elasticsearch versions since 0.90.x but you have to use a matching major version:

Set your requirements in your or requirements.txt is:

# Elasticsearch 6.x

# Elasticsearch 5.x

# Elasticsearch 2.x

Install via pip;

$ pip install elasticsearch
from elasticsearch import Elasticsearch

es = Elasticsearch([''])
from datetime import datetime
from elasticsearch import Elasticsearch
es = Elasticsearch([''])

doc = {
    'author': 'kimchy',
    'text': 'Elasticsearch: cool. bonsai cool.'

# ignore 400 cause by IndexAlreadyExistsException when creating an index
es.indices.create(index='test-index', ignore=400)

# create tweet
res = es.index(index="test-index", doc_type='tweet', id=1, body=doc)

# get tweet
res = es.get(index="test-index", doc_type='tweet', id=1)

# search tweet
res ="test-index", body={"query": {"match_all": {}}})
print("Got %d Hits:" % res['hits']['total'])
for hit in res['hits']['hits']:
    print("%(author)s: %(text)s" % hit["_source"])

The library is compatible with all Elasticsearch versions since 1.x but you have to use a matching major version:

# Elasticsearch 6.x

# Elasticsearch 5.x

# Elasticsearch 2.x

# Elasticsearch 1.x

You can either manually pass your connection instance to each request or set default connection for all requests.

s = Search(using=Elasticsearch(''))

To define a default connection that will be used globally, use the connections module and the create_connection method:

from elasticsearch_dsl import connections

connections.create_connection(hosts=[''], timeout=20)

You can create model-like wrapper for your documents via using DocType class. It can provide mapping and settings for Elasticsearch.

from elasticsearch_dsl import DocType, Date, Nested, Boolean, \
    analyzer, InnerDoc, Completion, Keyword, Text

html_strip = analyzer('html_strip',
    filter=["standard", "lowercase", "stop", "snowball"],

class Comment(InnerDoc):
    author = Text(fields={'raw': Keyword()})
    content = Text(analyzer='snowball')

class Post(DocType):
    title = Text()
    title_suggest = Completion()
    published = Boolean()
    category = Text(
        fields={'raw': Keyword()}

    comments = Nested(Comment)

    class Meta:
        index = 'blog'

    def add_comment(self, author, content):
          Comment(author=author, content=content))

    def save(self, ** kwargs):
        return super().save(** kwargs)

Also you can explicitly create index and provide settings at index;

from elasticsearch_dsl import Index, DocType, Text, analyzer

blogs = Index('blogs')

# define aliases

# register a doc_type with the index

# can also be used as class decorator when defining the DocType
class Post(DocType):
    title = Text()

# You can attach custom analyzers to the index

html_strip = analyzer('html_strip',
    filter=["standard", "lowercase", "stop", "snowball"],


# delete the index, ignore if it doesn't exist

# create the index in elasticsearch

Create and save documents to Elasticsearch;

# instantiate the document
first = Post(title='My First Blog Post, yay!', published=True)
# assign some field values, can be values or lists of values
first.category = ['everything', 'nothing']
# every document has an id in meta = 47

# save the document into the cluster
# by calling .search we get back a standard Search object
s =
# the search is already limited to the index and doc_type of our document
s = s.filter('term', published=True).query('match', title='first')

results = s.execute()

# when you execute the search the results are wrapped in your document class (Post)
for post in results:
    print(post.meta.score, post.title)