myarik / django-rest-elasticsearch

Elasticsearch support for Django REST Framework
Other
192 stars 38 forks source link

Elasticsearch for Django REST Framework

Build Status

About

Django REST Elasticsearch provides the easy way for integration Django REST Framework and Elasticsearch. The library uses Elasticsearch DSL library (elasticsearch-dsl-py) It is a high-level library to the official low-level client.

Requirements

Example

Let's take a look at a quick example of using Django REST Elasticsearch to build a simple application.

Install using pip...

pip install django-rest-elasticsearch

Let's create a simple Django model

class Blog(models.Model):
    title = models.CharField(_('Title'), max_length=1000)
    created_at = models.DateTimeField(_('Created at'), auto_now_add=True)
    body = models.TextField(_('Body'))
    tags = ArrayField(models.CharField(max_length=200), blank=True, null=True)
    is_published = models.BooleanField(_('Is published'), default=False)

    def __str__(self):
        return self.title

Create a DocType to represent our Blog model


from elasticsearch_dsl import Document, Date, Integer, Keyword, Text, GeoPoint

class BlogIndex(Document):
    pk = Integer()
    title = Text(fields={'raw': Keyword()})
    created_at = Date()
    body = Text()
    tags = Keyword(multi=True)
    is_published = Boolean()
    location = GeoPoint()

    class Index:
        name = 'blog'

After, create the mappings in Elasticsearch

BlogIndex.init()

Finally, create a view. The view provides search by a word in a title and filtering by tags.

from rest_framework_elasticsearch import es_views, es_pagination, es_filters

class BlogView(es_views.ListElasticAPIView):
    es_client = es_client
    es_model = BlogIndex
    es_pagination_class = es_pagination.ElasticLimitOffsetPagination
    es_filter_backends = (
        es_filters.ElasticFieldsFilter,
        es_filters.ElasticFieldsRangeFilter,
        es_filters.ElasticSearchFilter,
        es_filters.ElasticOrderingFilter,
        es_filters.ElasticGeoBoundingBoxFilter
    )
    es_ordering = 'created_at'
    es_filter_fields = (
        es_filters.ESFieldFilter('tag', 'tags'),
    )
    es_range_filter_fields = (
        es_filters.ESFieldFilter('created_at'),
    )
    es_search_fields = (
        'tags',
        'title',
    )

    es_geo_location_field = es_filters.ESFieldFilter('location')
    es_geo_location_field_name = 'location'

This will allow the client to filter the items in the list by making queries such as:

http://example.com/blogs/api/list?search=elasticsearch
http://example.com/blogs/api/list?tag=opensource
http://example.com/blogs/api/list?tag=opensource,aws
http://example.com/blogs/api/list?to_created_at=2020-10-01&from_created_at=2017-09-01

# ElasticGeoBoundingBoxFilter expects format {top left lat, lon}|{bottom right lat, lon}
http://example.com/blogs/api/list?location=25.55235365216549,120.245361328125|21.861498734372567,122.728271484375

# ElasticGeoDistanceFilter expects format {distance}{unit}|{lat}|{lon}
http://example.com/blogs/api/list?location=100000km|12.04|-63.93

Development

Activate Virtual Environment virtualenvs.

$ virtualenv venv
$ source venv/bin/activate

To run all of the tests for django-rest-elasticsearch, run:

$ python setup.py test

Use the pytest for running scripts

By default, the test connection is attempted at localhost:9200, based on the defaults specified in the elasticsearch-py Connection class. Elasticsearch instance at localhost:9200 does not meet these requirements, it is possible to specify a different test Elasticsearch server through the TEST_ES_SERVER environment variable.

$ TEST_ES_SERVER=my-test-server:9201 pytest

For running tests in ralease environments use tox

$ tox

Docker

This package also can be ran using Docker and the default entrypoint run the pytests.

docker-compose up

Documentation

Documentation is available at http://django-rest-elasticsearch.readthedocs.io