django-elasticsearch-dsl-drf¶
Integrate Elasticsearch DSL with Django REST framework in the shortest way possible, with least efforts possible.
Package provides views, serializers, filter backends, pagination and other handy add-ons.
You are expected to use django-elasticsearch-dsl for defining your Elasticsearch documents.
Prerequisites¶
- Django 1.8, 1.9, 1.10, 1.11, 2.0, 2.1 and 2.2.
- Python 2.7, 3.5, 3.6, 3.7
- Elasticsearch 2.x, 5.x, 6.x
Main features and highlights¶
- Dynamic serializer for Documents.
- Search filter backend.
- Ordering filter backend.
- Filtering filter backend (big variety of
native- and functional- query lookups, such as
gt
,gte
,lt
,lte
,endswith
,contains
,wildcard
,exists
,exclude
,isnull
,range
,in
,prefix
(same asstartswith
),term
andterms
is implemented. - Geo-spatial filtering filter backend (the
following filters implemented:
geo_distance
,geo_polygon
andgeo_bounding_box
). - Geo-spatial ordering filter backend (the
following filters implemented:
geo_distance
). - Faceted search filter backend.
- Post-filter filter backend.
- Nested filtering filter backend.
- Highlight backend.
- Suggester filter backend.
- Functional suggester filter backend.
- Pagination (Page number and limit/offset pagination).
- Ids filter backend.
- Multi match search filter backend.
- Simple search query search filter backend.
- More-like-this support (detail action).
- Global aggregations support.
- Source filter backend.
Demo¶
A frontend demo (React based) is available. See the dedicated docs for more information.
To bootstrap evaluation, clone the repository locally and run docker-compose.
docker-compose up
It will set up:
- Elasticsearch on http://localhost:9200
- Django REST framework on http://localhost:8000
- React on http://localhost:3000
Installation¶
Install latest stable version from PyPI:
pip install django-elasticsearch-dsl-drf
or latest stable version from GitHub:
pip install https://github.com/barseghyanartur/django-elasticsearch-dsl-drf/archive/stable.tar.gz
or latest stable version from BitBucket:
pip install https://bitbucket.org/barseghyanartur/django-elasticsearch-dsl-drf/get/stable.tar.gz
Add
rest_framework
,django_elasticsearch_dsl
anddjango_elasticsearch_dsl_drf
toINSTALLED_APPS
:INSTALLED_APPS = ( # ... # REST framework 'rest_framework', # Django Elasticsearch integration 'django_elasticsearch_dsl', # Django REST framework Elasticsearch integration (this package) 'django_elasticsearch_dsl_drf', # ... )
Quick start¶
Perhaps the easiest way to get acquainted with django-elasticsearch-dsl-drf
is to read the quick start tutorial.
See it as a guide of diving into integration of Elasticsearch with Django with very low knowledge entry level.
Testing¶
Project is covered with tests.
To test with all supported Python/Django versions type:
tox
To test against specific environment, type:
tox -e py37-django21
To test just your working environment type:
./runtests.py
To run a single test in your working environment type:
./runtests.py src/django_elasticsearch_dsl_drf/tests/test_filtering.py
Or:
./manage.py test django_elasticsearch_dsl_drf.tests.test_ordering
To run a single test class in a given test module in your working environment type:
./runtests.py src/django_elasticsearch_dsl_drf/tests/test_suggesters.py::TestSuggesters
It’s assumed that you have all the requirements installed. If not, first install the test requirements:
pip install -r examples/requirements/test.txt
Writing documentation¶
Keep the following hierarchy.
=====
title
=====
header
======
sub-header
----------
sub-sub-header
~~~~~~~~~~~~~~
sub-sub-sub-header
^^^^^^^^^^^^^^^^^^
sub-sub-sub-sub-header
++++++++++++++++++++++
sub-sub-sub-sub-sub-header
**************************
Author¶
Artur Barseghyan <artur.barseghyan@gmail.com>
Project documentation¶
Contents:
Table of Contents
Dependencies¶
elasticsearch and elasticsearch-dsl
Depending on your Elasticsearch version (either 2.x, 5.x or 6.x) you should
use 2.x, 5.x or 6.x versions of the elasticsearch
and elasticsearch-dsl
packages accordingly.
django-elasticsearch-dsl
You are advised to use the latest version of django-elasticsearch-dsl.
Django/ Django REST Framework
Initial version of this package was written for djangorestframework 3.6.2.
Starting from version 0.18 support for Django versions prior 1.11 and Django REST Framework versions prior 3.9 has been dropped.
Current compatibility matrix is:
Django | Django REST Framework |
1.11 | 3.9.3 |
2.0 | 3.9.3 |
2.1 | 3.9.3 |
2.2 | 3.9.3 |
The version 0.17.7 has been tested with the following versions of Django and Django REST Framework:
Django | Django REST Framework |
1.8 | 3.6.2 |
1.9 | 3.6.2 |
1.10 | 3.6.2 |
1.11 | 3.7.7 |
2.0 | 3.7.7 |
2.1 | 3.8.2 |
2.2 | 3.9.2 |
Installing Elasticsearch¶
For development and testing purposes, it’s often handy to be able to quickly switch between different Elasticsearch versions. Since this packages supports 2.x, 5.x and 6.x branches, you could make use of the following boxes/containers for development and testing.
For all containers/boxes mentioned below, no authentication is required (for Elasticsearch).
Docker¶
2.x¶
docker pull elasticsearch:2.4.6
docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" elasticsearch:2.4.6
5.x¶
docker pull docker.elastic.co/elasticsearch/elasticsearch:5.5.3
docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:5.5.3
6.x¶
6.3.2
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.3.2
docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
6.4.0
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.4.0
docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:6.4.0
7.x¶
7.1.1
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.1.1
docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:7.1.1
Quick start¶
The best way to get acquainted with django-elasticsearch-dsl-drf
.
See it as a guide of diving into integration of Elasticsearch with Django with very low knowledge entry level.
Contents:
Table of Contents
Installation¶
Install latest stable version from PyPI:
pip install django-elasticsearch-dsl-drf
Add
rest_framework
,django_elasticsearch_dsl
anddjango_elasticsearch_dsl_drf
toINSTALLED_APPS
:INSTALLED_APPS = ( # ... # REST framework 'rest_framework', # Django Elasticsearch integration 'django_elasticsearch_dsl', # Django REST framework Elasticsearch integration (this package) 'django_elasticsearch_dsl_drf', # ... )
Basic Django REST framework and
django-elasticsearch-dsl
configuration:REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.BasicAuthentication', 'rest_framework.authentication.SessionAuthentication', ), 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE': 100, 'ORDERING_PARAM': 'ordering', } # Elasticsearch configuration ELASTICSEARCH_DSL = { 'default': { 'hosts': 'localhost:9200' }, }
Example app¶
To get started, let’s imagine we have a simple book register with a couple of models.
- Publisher model: The book publisher model. Each book might have only one
publisher (
ForeignKey
relation). - Author model: The book author model. Each book might have unlimited number
of authors (
ManyToMany
relation). - Tag model: The tag model. Each book might have unlimited number of
tags (
ManyToMany
relation). - Book model: The book model.
To keep things separate, our Django models will reside in the books
app.
Elasticsearch documents and Django REST framework views will be defined in a
search_indexes
app. Both of the apps should be added to the
INSTALLED_APPS
.
INSTALLED_APPS = (
# ...
'books', # Books application
'search_indexes', # Elasticsearch integration with the Django
# REST framework
# ...
)
Sample models¶
Content of the books/models.py
file. Additionally, see the code comments.
Required imports¶
Imports required for model definition.
books/models/book.py
import json
from django.conf import settings
from django.db import models
from django.utils.translation import ugettext, ugettext_lazy as _
from six import python_2_unicode_compatible
Book statuses¶
books/models/book.py
# States indicate the publishing status of the book. Publishing might
# be in-progress, not yet published, published, rejected, etc.
BOOK_PUBLISHING_STATUS_PUBLISHED = 'published'
BOOK_PUBLISHING_STATUS_NOT_PUBLISHED = 'not_published'
BOOK_PUBLISHING_STATUS_IN_PROGRESS = 'in_progress'
BOOK_PUBLISHING_STATUS_CANCELLED = 'cancelled'
BOOK_PUBLISHING_STATUS_REJECTED = 'rejected'
BOOK_PUBLISHING_STATUS_CHOICES = (
(BOOK_PUBLISHING_STATUS_PUBLISHED, "Published"),
(BOOK_PUBLISHING_STATUS_NOT_PUBLISHED, "Not published"),
(BOOK_PUBLISHING_STATUS_IN_PROGRESS, "In progress"),
(BOOK_PUBLISHING_STATUS_CANCELLED, "Cancelled"),
(BOOK_PUBLISHING_STATUS_REJECTED, "Rejected"),
)
BOOK_PUBLISHING_STATUS_DEFAULT = BOOK_PUBLISHING_STATUS_PUBLISHED
Publisher model¶
books/models/book.py
@python_2_unicode_compatible
class Publisher(models.Model):
"""Publisher."""
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
latitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
longitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return self.name
@property
def location_field_indexing(self):
"""Location for indexing.
Used in Elasticsearch indexing/tests of `geo_distance` native filter.
"""
return {
'lat': self.latitude,
'lon': self.longitude,
}
Author model¶
books/models/author.py
@python_2_unicode_compatible
class Author(models.Model):
"""Author."""
salutation = models.CharField(max_length=10)
name = models.CharField(max_length=200)
email = models.EmailField()
headshot = models.ImageField(upload_to='authors', null=True, blank=True)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return self.name
Tag model¶
books/models/tag.py
class Tag(models.Model):
"""Simple tag model."""
title = models.CharField(max_length=255, unique=True)
class Meta(object):
"""Meta options."""
verbose_name = _("Tag")
verbose_name_plural = _("Tags")
def __str__(self):
return self.title
Book model¶
books/models/book.py
@python_2_unicode_compatible
class Book(models.Model):
"""Book."""
title = models.CharField(max_length=100)
description = models.TextField(null=True, blank=True)
summary = models.TextField(null=True, blank=True)
authors = models.ManyToManyField('books.Author', related_name='books')
publisher = models.ForeignKey(Publisher, related_name='books')
publication_date = models.DateField()
state = models.CharField(max_length=100,
choices=BOOK_PUBLISHING_STATUS_CHOICES,
default=BOOK_PUBLISHING_STATUS_DEFAULT)
isbn = models.CharField(max_length=100, unique=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
pages = models.PositiveIntegerField(default=200)
stock_count = models.PositiveIntegerField(default=30)
tags = models.ManyToManyField('books.Tag',
related_name='books',
blank=True)
class Meta(object):
"""Meta options."""
ordering = ["isbn"]
def __str__(self):
return self.title
# The only publisher information we're going to need in our document
# is the publisher name. Since publisher isn't a required field,
# we define a properly on a model level to avoid indexing errors on
# non-existing relation.
@property
def publisher_indexing(self):
"""Publisher for indexing.
Used in Elasticsearch indexing.
"""
if self.publisher is not None:
return self.publisher.name
# As of tags, again, we only need a flat list of tag names, on which
# we can filter. Therefore, we define a properly on a model level,
# which will return a JSON dumped list of tags relevant to the
# current book model object.
@property
def tags_indexing(self):
"""Tags for indexing.
Used in Elasticsearch indexing.
"""
return [tag.title for tag in self.tags.all()]
Admin classes¶
This is just trivial. A couple of correspondent admin classes in order to ba able to fill some data.
books/admin.py
from django.contrib import admin
from .models import *
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
"""Book admin."""
list_display = ('title', 'isbn', 'price', 'publication_date')
search_fields = ('title',)
filter_horizontal = ('authors', 'tags',)
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
"""Author admin."""
list_display = ('name', 'email',)
search_fields = ('name',)
@admin.register(Publisher)
class PublisherAdmin(admin.ModelAdmin):
"""Publisher admin."""
list_display = ('name',)
search_fields = ('name',)
@admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
"""Tag admin."""
list_display = ('title',)
search_fields = ('title',)
Create database tables¶
For now, just run the migrations to create the database tables.
./manage.py makemigrations books
./manage.py migrate books
Fill in some data¶
If you have followed the instructions, you should now be able to log into the Django admin and create a dozen of Book/Author/Publisher/Tag records in admin.
http://localhost:8000/admin/books/publisher/
http://localhost:8000/admin/books/author/
http://localhost:8000/admin/books/tag/
http://localhost:8000/admin/books/book/
Once you’ve done that, proceed to the next step.
Sample document¶
In Elasticsearch, a document is a basic unit of information that can be indexed. For example, you can have a document for a single customer, another document for a single product, and yet another for a single order. This document is expressed in JSON (JavaScript Object Notation) which is an ubiquitous internet data interchange format.
Within an index/type, you can store as many documents as you want. Note that although a document physically resides in an index, a document actually must be indexed/assigned to a type inside an index.
Simply said, you could see an Elasticsearch index as a database and a document as a database table (which makes a Document definition in Elasticsearch DSL similar to a Django Model definition).
Often, complex SQL model structures are flatterned in Elasticsearch indexes/documents. Nested relations are denormalized.
In our example, all 4 models (Author
, Publisher
, Tag
, Book
)
would be flatterned into a single BookDocument
, which would hold all
the required information.
Content of the search_indexes/documents/book.py
file. Additionally, see
the code comments.
Required imports¶
search_indexes/documents/book.py
from django.conf import settings
from django_elasticsearch_dsl import DocType, Index, fields
from elasticsearch_dsl import analyzer
from books.models import Book
Index definition¶
To separate dev/test/staging/production indexes, the following approach is recommended.
Note
In the examples below the search_indexes.documents.book
and
search_indexes.documents.publisher
are the pythonic file paths to
modules where documents are defined.
settings/base.py
Note
In this example, book
and publisher
are Elasticsearch index names.
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.book': 'book',
'search_indexes.documents.publisher': 'publisher',
}
settings/testing.py
Note
In this example, test_book
and test_publisher
are Elasticsearch
index names.
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.book': 'test_book',
'search_indexes.documents.publisher': 'test_publisher',
}
settings/production.py
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.book': 'prod_book',
'search_indexes.documents.publisher': 'prod_publisher',
}
search_indexes/documents/book.py
# Name of the Elasticsearch index
INDEX = Index(settings.ELASTICSEARCH_INDEX_NAMES[__name__])
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
Custom analyzers¶
html_strip = analyzer(
'html_strip',
tokenizer="standard",
filter=["standard", "lowercase", "stop", "snowball"],
char_filter=["html_strip"]
)
Document definition¶
search_indexes/documents/book.py
@INDEX.doc_type
class BookDocument(DocType):
"""Book Elasticsearch document."""
id = fields.IntegerField(attr='id')
title = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
description = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
summary = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
publisher = fields.StringField(
attr='publisher_indexing',
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
publication_date = fields.DateField()
state = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
isbn = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
price = fields.FloatField()
pages = fields.IntegerField()
stock_count = fields.IntegerField()
tags = fields.StringField(
attr='tags_indexing',
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword', multi=True),
'suggest': fields.CompletionField(multi=True),
},
multi=True
)
class Meta(object):
"""Meta options."""
model = Book # The model associate with this DocType
Syncing Django’s database with Elasticsearch indexes¶
So far, we have a couple of Django models and a single (decentralized) Elasticsearch index/document (Book).
Full database sync¶
The excellent django-elasticsearch-dsl
library makes a good job of keeping
the Book index fresh. It makes use of signals, so whenever the Book model
is changed, the correspondent BookDocument indexes would be updated.
To simply run the full sync between Django’s database and Elasticsearch, do as follows:
Create Elasticsearch indexes:
./manage.py search_index --create -f
Sync the data:
./manage.py search_index --populate -f
However, in case if a Tag, Publisher or Author models change, the Book index would not be automatically updated.
Sample partial sync (using custom signals)¶
In order to keep indexes fresh, you will have to write a couple of simple lines of code (using Django’s signals). Whenever a change is made to any of the Tag, Publisher or Author models, we’re going to update the correspondent BookDocument index.
search_indexes/signals.py
from django.db.models.signals import post_save, post_delete
from django.dispatch import receiver
from django_elasticsearch_dsl.registries import registry
Sample serializer¶
At this step we’re going to define a serializer to be used in the Django REST framework ViewSet.
Content of the search_indexes/serializers.py
file. Additionally, see
the code comments.
Required imports¶
search_indexes/serializers/book.py
import json
from rest_framework import serializers
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
from .documents import BookDocument
Serializer definition¶
Simplest way to create a serializer, is to just specify which fields are needed to be serialized and leave it further to the dynamic serializer.
search_indexes/serializers/book.py
class BookDocumentSerializer(DocumentSerializer):
"""Serializer for the Book document."""
class Meta(object):
"""Meta options."""
# Specify the correspondent document class
document = BookDocument
# List the serializer fields. Note, that the order of the fields
# is preserved in the ViewSet.
fields = (
'id',
'title',
'description',
'summary',
'publisher',
'publication_date',
'state',
'isbn',
'price',
'pages',
'stock_count',
'tags',
)
However, if dynamic serializer doesn’t work for your or you want to customize
too many things, you are free to use standard Serializer
class of the
Django REST framework.
search_indexes/serializers/book.py
class BookDocumentSerializer(serializers.Serializer):
"""Serializer for the Book document."""
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(read_only=True)
description = serializers.CharField(read_only=True)
summary = serializers.CharField(read_only=True)
publisher = serializers.CharField(read_only=True)
publication_date = serializers.DateField(read_only=True)
state = serializers.CharField(read_only=True)
isbn = serializers.CharField(read_only=True)
price = serializers.FloatField(read_only=True)
pages = serializers.IntegerField(read_only=True)
stock_count = serializers.IntegerField(read_only=True)
tags = serializers.SerializerMethodField()
class Meta(object):
"""Meta options."""
# List the serializer fields. Note, that the order of the fields
# is preserved in the ViewSet.
fields = (
'id',
'title',
'description',
'summary',
'publisher',
'publication_date',
'state',
'isbn',
'price',
'pages',
'stock_count',
'tags',
)
def get_tags(self, obj):
"""Get tags."""
if obj.tags:
return list(obj.tags)
else:
return []
ViewSet definition¶
At this step, we’re going to define Django REST framework ViewSets.
Content of the search_indexes/viewsets.py
file. Additionally, see
the code comments.
Required imports¶
search_indexes/viewsets/book.py
from django_elasticsearch_dsl_drf.constants import (
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_RANGE,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
LOOKUP_QUERY_EXCLUDE,
)
from django_elasticsearch_dsl_drf.filter_backends import (
FilteringFilterBackend,
IdsFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import BaseDocumentViewSet
from django_elasticsearch_dsl_drf.pagination import PageNumberPagination
from .documents import BookDocument, PublisherDocument
from .serializers import BookDocumentSerializer
ViewSet definition¶
search_indexes/viewsets/book.py
class BookDocumentView(BaseDocumentViewSet):
"""The BookDocument view."""
document = BookDocument
serializer_class = BookDocumentSerializer
pagination_class = PageNumberPagination
lookup_field = 'id'
filter_backends = [
FilteringFilterBackend,
IdsFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
]
# Define search fields
search_fields = (
'title',
'description',
'summary',
)
# Define filter fields
filter_fields = {
'id': {
'field': 'id',
# Note, that we limit the lookups of id field in this example,
# to `range`, `in`, `gt`, `gte`, `lt` and `lte` filters.
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'title': 'title.raw',
'publisher': 'publisher.raw',
'publication_date': 'publication_date',
'state': 'state.raw',
'isbn': 'isbn.raw',
'price': {
'field': 'price.raw',
# Note, that we limit the lookups of `price` field in this
# example, to `range`, `gt`, `gte`, `lt` and `lte` filters.
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'pages': {
'field': 'pages',
# Note, that we limit the lookups of `pages` field in this
# example, to `range`, `gt`, `gte`, `lt` and `lte` filters.
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'stock_count': {
'field': 'stock_count',
# Note, that we limit the lookups of `stock_count` field in
# this example, to `range`, `gt`, `gte`, `lt` and `lte`
# filters.
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'tags': {
'field': 'tags',
# Note, that we limit the lookups of `tags` field in
# this example, to `terms, `prefix`, `wildcard`, `in` and
# `exclude` filters.
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
'tags.raw': {
'field': 'tags.raw',
# Note, that we limit the lookups of `tags.raw` field in
# this example, to `terms, `prefix`, `wildcard`, `in` and
# `exclude` filters.
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
}
# Define ordering fields
ordering_fields = {
'id': 'id',
'title': 'title.raw',
'price': 'price.raw',
'state': 'state.raw',
'publication_date': 'publication_date',
}
# Specify default ordering
ordering = ('id', 'title', 'price',)
URLs¶
At this step, we’re going to define url patterns.
Content of the search_indexes/urls.py
file. Additionally, see
the code comments.
Required imports¶
search_indexes/urls.py
from django.conf.urls import url, include
from rest_framework.routers import DefaultRouter
from .views import BookDocumentView
Router definition¶
search_indexes/urls.py
router = DefaultRouter()
books = router.register(r'books',
BookDocumentView,
basename='bookdocument')
Check what you’ve done so far¶
At this point, you are one step away from a working example of integrating Elasticsearch DSL with Django.
URLs¶
If you didn’t add the urls of the search_indexes
example application to
your project’s global url patterns, make sure to do it now.
from django.conf.urls import include, url
from search_indexes import urls as search_index_urls
urlpatterns = [
# ...
# Search URLs
url(r'^search/', include(search_index_urls)),
# ...
]
Test in browser¶
Open the following URL in your browser.
http://localhost:8000/search/books/
Perform a number of lookups:
http://localhost:8001/search/books/?ids=54|55|56
http://localhost:8001/search/books/?summary__contains=photography
http://localhost:8001/search/books/?tags__contains=ython
http://localhost:8001/search/books/?state=published
http://localhost:8001/search/books/?pages__gt=10&pages__lt=30
Development and debugging¶
Profiling tools¶
Looking for profiling tools for Elasticsearch?
Try django-elasticsearch-debug-toolbar package. It’s implemented as a panel for the well known Django Debug Toolbar and gives you full insights on what’s happening on the side of Elasticsearch.
Installation¶
pip install django-debug-toolbar
pip install django-elasticsearch-debug-toolbar
Configuration¶
Change your development settings in the following way:
settings/dev.py
MIDDLEWARE_CLASSES += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
'debug_toolbar_force.middleware.ForceDebugToolbarMiddleware',
)
INSTALLED_APPS += (
'debug_toolbar',
'elastic_panel',
)
DEBUG_TOOLBAR_CONFIG = {
'INTERCEPT_REDIRECTS': False,
}
DEBUG_TOOLBAR_PANELS = (
# Defaults
'debug_toolbar.panels.versions.VersionsPanel',
'debug_toolbar.panels.timer.TimerPanel',
'debug_toolbar.panels.settings.SettingsPanel',
'debug_toolbar.panels.headers.HeadersPanel',
'debug_toolbar.panels.request.RequestPanel',
'debug_toolbar.panels.sql.SQLPanel',
'debug_toolbar.panels.staticfiles.StaticFilesPanel',
'debug_toolbar.panels.templates.TemplatesPanel',
'debug_toolbar.panels.cache.CachePanel',
'debug_toolbar.panels.signals.SignalsPanel',
'debug_toolbar.panels.logging.LoggingPanel',
'debug_toolbar.panels.redirects.RedirectsPanel',
# Additional
'elastic_panel.panel.ElasticDebugPanel',
)
Debugging¶
Although (the unbeatable) Kibana is strongly recommended for data analyses, there are other good tools worth mentioning. One of them is elasticsearch-head Elasticsearch 2.x plugin or a correspondent Chrome extension of the same plugin. You may find it very useful for quick data preview or testing Elasticsearch queries.
Filter usage examples¶
Example usage of filtering backends.
Contents:
Table of Contents
Search¶
Query param name reserved for search is search
. Make sure your models and
documents do not have it as a field or attribute.
Multiple search terms are joined with OR
.
Let’s assume we have a number of Book items with fields title
,
description
and summary
.
Search in all fields¶
Search in all fields (name
, address
, city
, state_province
and
country
) for word “reilly”.
http://127.0.0.1:8080/search/publisher/?search=reilly
Search a single term on specific field¶
In order to search in specific field (name
) for term “reilly”, add
the field name separated with :
to the search term.
http://127.0.0.1:8080/search/publisher/?search=name:reilly
Search for multiple terms¶
In order to search for multiple terms “reilly”, “bloomsbury” add
multiple search
query params.
http://127.0.0.1:8080/search/publisher/?search=reilly&search=bloomsbury
Search for multiple terms in specific fields¶
In order to search for multiple terms “reilly”, “bloomsbury” in specific
fields add multiple search
query params and field names separated with
:
to each of the search terms.
http://127.0.0.1:8080/search/publisher/?search=name:reilly&search=city:london
Filtering¶
Supported lookups¶
Native¶
The following native (to Elasticsearch) filters/lookups are implemented:
Find documents which contain the exact term specified in the field specified.
http://127.0.0.1:8080/search/books/?tags__term=education&tags__term=economy
Find documents which contain any of the exact terms specified in the field specified. Note, that multiple values are separated with double underscores __.
http://localhost:8000/api/articles/?id=1&id=2&id=3
http://localhost:8000/api/articles/?id__terms=1__2__3
Find documents where the field specified contains values (dates, numbers, or strings) in the range specified.
From, to
http://localhost:8000/api/users/?age__range=16__67
From, to, boost
http://localhost:8000/api/users/?age__range=16__67__2.0
Find documents where the field specified contains any non-null value.
http://localhost:8000/api/articles/?tags__exists=true
Find documents where the field specified contains terms which begin with the exact prefix specified.
http://localhost:8000/api/articles/?tags__prefix=bio
Functional¶
The following functional (non-native to Elasticsearch, but common in Django) filters/lookups are implemented:
Case-insensitive containment test.
http://localhost:8000/api/articles/?state__contains=lishe
Should match: published, not published, needs polishing.
Case-sensitive ends-with.
http://localhost:8000/api/articles/?state__endswith=lished
Should match: published, not published.
Search backends¶
Compound search filter backend¶
Compound search filter backend aims to replace old style SearchFilterBackend.
Sample view¶
from django_elasticsearch_dsl_drf.filter_backends import (
DefaultOrderingFilterBackend,
CompoundSearchFilterBackend,
OrderingFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from .documents import BookDocument
from .serializers import BookDocumentSerializer
class BookCompoundSearchBackendDocumentViewSet(DocumentViewSet):
document = BookDocument
serializer_class = BookDocumentSerializer
lookup_field = 'id'
filter_backends = [
# ...
OrderingFilterBackend,
DefaultOrderingFilterBackend,
CompoundSearchFilterBackend,
# ...
]
multi_match_search_fields = (
'title',
'description',
'summary',
)
ordering = ('_score', 'id', 'title', 'price',)
Sample request¶
http://localhost:8000/search/books-compound-search-backend/?search=enim
Generated query¶
{
"from": 0,
"sort": [
"id",
"title",
"price"
],
"size": 23,
"query": {
"bool": {
"should": [
{
"match": {
"title": {
"query": "enim"
}
}
},
{
"match": {
"description": {
"query": "enim"
}
}
},
{
"match": {
"summary": {
"query": "enim"
}
}
}
]
}
}
}
Multi match search filter backend¶
Document and serializer definition are trivial (there are lots of examples in other sections).
Sample view¶
from django_elasticsearch_dsl_drf.filter_backends import (
DefaultOrderingFilterBackend,
MultiMatchSearchFilterBackend,
OrderingFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from .documents import BookDocument
from .serializers import BookDocumentSerializer
class BookMultiMatchSearchFilterBackendDocumentViewSet(DocumentViewSet):
document = BookDocument
serializer_class = BookDocumentSerializer
lookup_field = 'id'
filter_backends = [
# ...
OrderingFilterBackend,
DefaultOrderingFilterBackend,
MultiMatchSearchFilterBackend,
# ...
]
multi_match_search_fields = {
'title': {'boost': 4},
'summary': {'boost': 2},
'description': None,
}
ordering = ('_score', 'id', 'title', 'price',)
Sample request¶
Note
Multiple search params (search_multi_match) are not supported. Even if you provide multiple search params, the first one would be picked, having the rest simply ignored.
http://localhost:8000/search/books-multi-match-search-backend/?search_multi_match=debitis%20enim
Generated query¶
{
"from": 0,
"query": {
"multi_match": {
"query": "debitis enim",
"fields": [
"summary^2",
"description",
"title^4"
]
}
},
"size": 38,
"sort": [
"_score",
"id",
"title",
"price"
]
}
Options¶
All standard multi match query options are available/tunable with help of
multi_match_options
view property.
Selective list of available options:
- operator
- type
- analyzer
- tie_breaker
Type options¶
See the Elasticsearch docs for detailed explanation.
- best_fields
- most_fields
- cross_fields
- phrase
- phrase_prefix
Example
class BookMultiMatchSearchFilterBackendDocumentViewSet(DocumentViewSet):
# ...
multi_match_options = {
'type': 'phrase'
}
Operator options¶
Can be either and
or or
.
Simple query string filter backend¶
Document and serializer definition are trivial (there are lots of examples in other sections).
Sample view¶
from django_elasticsearch_dsl_drf.filter_backends import (
DefaultOrderingFilterBackend,
SimpleQueryStringSearchFilterBackend,
OrderingFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from .documents import BookDocument
from .serializers import BookDocumentSerializer
class BookSimpleQueryStringSearchFilterBackendDocumentViewSet(DocumentViewSet):
document = BookDocument
serializer_class = BookDocumentSerializer
lookup_field = 'id'
filter_backends = [
# ...
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SimpleQueryStringSearchFilterBackend,
# ...
]
simple_query_string_search_fields = {
'title': {'boost': 4},
'summary': {'boost': 2},
'description': None,
}
ordering = ('_score', 'id', 'title', 'price',)
Sample request 1¶
Note
Multiple search params (search_simple_query_string) are not supported. Even if you provide multiple search params, the first one would be picked, having the rest simply ignored.
http://localhost:8000/search/books-simple-query-string-search-backend/?search_simple_query_string="chapter%20II"%20%2Bfender
Generated query 1¶
{
"query": {
"simple_query_string": {
"query": "\"chapter II\" +fender",
"default_operator": "and",
"fields": [
"title",
"description",
"summary"
]
}
},
"sort": [
"_score",
"id",
"title",
"price"
],
"from": 0,
"size": 1
}
Sample request 2¶
Note
Multiple search params (search_simple_query_string) are not supported. Even if you provide multiple search params, the first one would be picked, having the rest simply ignored.
http://localhost:8000/search/books-simple-query-string-search-backend/?search_simple_query_string="chapter%20II"%20%2B(shutting%20|%20fender)
Generated query 2¶
{
"query": {
"simple_query_string": {
"query": "\"chapter II\" +(shutting | fender)",
"default_operator": "and",
"fields": [
"title",
"description",
"summary"
]
}
},
"sort": [
"_score",
"id",
"title",
"price"
],
"from": 0,
"size": 2
}
Sample request 3¶
Note
Multiple search params (search_simple_query_string) are not supported. Even if you provide multiple search params, the first one would be picked, having the rest simply ignored.
http://localhost:8000/search/books-simple-query-string-search-backend/?search_simple_query_string=%22Pool%20of%20Tears%22%20-considering
Generated query 3¶
{
"query": {
"simple_query_string": {
"query": "\"Pool of Tears\" -considering",
"default_operator": "and",
"fields": [
"title",
"description",
"summary"
]
}
},
"sort": [
"_score",
"id",
"title",
"price"
],
"from": 0,
"size": 1
}
Options¶
All standard multi match query options are available/tunable with help of
simple_query_string_options
view property.
Selective list of available options:
- default_operator
Default Operator options¶
Can be either and
or or
.
Example
class BookSimpleQueryStringSearchFilterBackendDocumentViewSet(DocumentViewSet):
# ...
simple_query_string_options = {
"default_operator": "and",
}
Basic usage examples¶
Basic Django REST framework integration example
See the example project for sample models/views/serializers.
Contents:
Table of Contents
Example app¶
Sample models¶
books/models/publisher.py
class Publisher(models.Model):
"""Publisher."""
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
latitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
longitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return self.name
@property
def location_field_indexing(self):
"""Location for indexing.
Used in Elasticsearch indexing/tests of `geo_distance` native filter.
"""
return {
'lat': self.latitude,
'lon': self.longitude,
}
Sample document¶
search_indexes/documents/publisher.py
from django_elasticsearch_dsl import DocType, Index, fields
from elasticsearch_dsl import analyzer
from books.models import Publisher
# Name of the Elasticsearch index
PUBLISHER_INDEX = Index('publisher')
# See Elasticsearch Indices API reference for available settings
PUBLISHER_INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
@PUBLISHER_INDEX.doc_type
class PublisherDocument(DocType):
"""Publisher Elasticsearch document."""
id = fields.IntegerField(attr='id')
name = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
info = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
address = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
city = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
state_province = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
country = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
website = fields.StringField()
# Location
location = fields.GeoPointField(attr='location_field_indexing')
class Meta(object):
"""Meta options."""
model = Publisher # The model associate with this DocType
Sample serializer¶
search_indexes/serializers/book.py
import json
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
class PublisherDocumentSerializer(DocumentSerializer):
"""Serializer for Publisher document."""
location = serializers.SerializerMethodField()
class Meta(object):
"""Meta options."""
# Note, that since we're using a dynamic serializer,
# we only have to declare fields that we want to be shown. If
# somehow, dynamic serializer doesn't work for you, either extend
# or declare your serializer explicitly.
fields = (
'id',
'name',
'info',
'address',
'city',
'state_province',
'country',
'website',
)
def get_location(self, obj):
"""Represent location value."""
try:
return obj.location.to_dict()
except:
return {}
Sample view¶
search_indexes/views/publisher.py
from django_elasticsearch_dsl_drf.constants import (
LOOKUP_FILTER_GEO_DISTANCE,
)
from django_elasticsearch_dsl_drf.filter_backends import (
FilteringFilterBackend,
OrderingFilterBackend,
SearchFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
# Example app models
from search_indexes.documents.publisher import PublisherDocument
from search_indxes.serializers import PublisherDocumentSerializer
class PublisherDocumentView(DocumentViewSet):
"""The PublisherDocument view."""
document = PublisherDocument
serializer_class = PublisherDocumentSerializer
lookup_field = 'id'
filter_backends = [
FilteringFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
]
# Define search fields
search_fields = (
'name',
'info',
'address',
'city',
'state_province',
'country',
)
# Define filtering fields
filter_fields = {
'id': None,
'name': 'name.raw',
'city': 'city.raw',
'state_province': 'state_province.raw',
'country': 'country.raw',
}
# Define ordering fields
ordering_fields = {
'id': None,
'name': None,
'city': None,
'country': None,
}
# Specify default ordering
ordering = ('id', 'name',)
# Define geo-spatial filtering fields
geo_spatial_filter_fields = {
'location': {
'lookups': [
LOOKUP_FILTER_GEO_DISTANCE,
],
},
}
Usage example¶
Considering samples above, you should be able to perform the search, sorting and filtering actions described below.
Sample queries¶
Query param name reserved for search is search
. Make sure your models and
documents do not have it as a field or attribute.
Multiple search terms are joined with OR
.
Let’s assume we have a number of Book items with fields title
,
description
and summary
.
Search in all fields
Search in all fields (name
, address
, city
, state_province
and
country
) for word “reilly”.
http://127.0.0.1:8080/search/publisher/?search=reilly
Search a single term on specific field
In order to search in specific field (name
) for term “reilly”, add
the field name separated with :
to the search term.
http://127.0.0.1:8080/search/publisher/?search=name:reilly
Search for multiple terms
In order to search for multiple terms “reilly”, “bloomsbury” add
multiple search
query params.
http://127.0.0.1:8080/search/publisher/?search=reilly&search=bloomsbury
Search for multiple terms in specific fields
In order to search for multiple terms “reilly”, “bloomsbury” in specific
fields add multiple search
query params and field names separated with
:
to each of the search terms.
http://127.0.0.1:8080/search/publisher/?search=name:reilly&search=city:london
Let’s assume we have a number of Publisher documents with in cities (Yerevan, Groningen, Amsterdam, London).
Multiple filter terms are joined with AND
.
Filter documents by single field
Filter documents by field (city
) “yerevan”.
http://127.0.0.1:8080/search/publisher/?city=yerevan
Filter documents by multiple fields
Filter documents by city
“Yerevan” and “Groningen”.
http://127.0.0.1:8080/search/publisher/?city__in=yerevan__groningen
Filter document by a single field
Filter documents by (field country
) “Armenia”.
http://127.0.0.1:8080/search/publisher/?country=armenia
Filter documents by multiple fields
Filter documents by multiple fields (field city
) “Yerevan” and “Amsterdam”
with use of functional in
query filter.
http://127.0.0.1:8080/search/publisher/?city__in=yerevan__amsterdam
You can achieve the same effect by specifying multiple filters (city
)
“Yerevan” and “Amsterdam”. Note, that in this case multiple filter terms are
joined with OR
.
http://127.0.0.1:8080/search/publisher/?city=yerevan&city=amsterdam
If you want the same as above, but joined with AND
, add __term
to each
lookup.
http://127.0.0.1:8080/search/publisher/?city__term=education&city__term=economy
Filter documents by a word part of a single field
Filter documents by a part word part in single field (city
) “ondon”.
http://127.0.0.1:8080/search/publisher/?city__wildcard=*ondon
Geo-distance filtering
Filter documents by radius of 100000km from the given location.
http://127.0.0.1:8000/search/publishers/?location__geo_distance=100000km__12.04__-63.93
The -
prefix means ordering should be descending.
Order documents by field (ascending)
Filter documents by field city
(ascending).
http://127.0.0.1:8080/search/publisher/?search=country:armenia&ordering=city
Order documents by field (descending)
Filter documents by field country
(descending).
http://127.0.0.1:8080/search/publisher/?ordering=-country
Order documents by multiple fields
If you want to order by multiple fields, use multiple ordering query params. In
the example below, documents would be ordered first by field country
(descending), then by field city
(ascending).
http://127.0.0.1:8080/search/publisher/?ordering=-country&ordering=city
Advanced usage examples¶
Advanced Django REST framework integration examples.
See the example project for sample models/views/serializers.
Contents:
Table of Contents
Example app¶
Sample models¶
books/models/publisher.py
import json
from django.conf import settings
from django.db import models
from django.utils.translation import ugettext, ugettext_lazy as _
from six import python_2_unicode_compatible
BOOK_PUBLISHING_STATUS_PUBLISHED = 'published'
BOOK_PUBLISHING_STATUS_NOT_PUBLISHED = 'not_published'
BOOK_PUBLISHING_STATUS_IN_PROGRESS = 'in_progress'
BOOK_PUBLISHING_STATUS_CANCELLED = 'cancelled'
BOOK_PUBLISHING_STATUS_REJECTED = 'rejected'
BOOK_PUBLISHING_STATUS_CHOICES = (
(BOOK_PUBLISHING_STATUS_PUBLISHED, "Published"),
(BOOK_PUBLISHING_STATUS_NOT_PUBLISHED, "Not published"),
(BOOK_PUBLISHING_STATUS_IN_PROGRESS, "In progress"),
(BOOK_PUBLISHING_STATUS_CANCELLED, "Cancelled"),
(BOOK_PUBLISHING_STATUS_REJECTED, "Rejected"),
)
BOOK_PUBLISHING_STATUS_DEFAULT = BOOK_PUBLISHING_STATUS_PUBLISHED
@python_2_unicode_compatible
class Publisher(models.Model):
"""Publisher."""
name = models.CharField(max_length=30)
info = models.TextField(null=True, blank=True)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
latitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
longitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return self.name
@property
def location_field_indexing(self):
"""Location for indexing.
Used in Elasticsearch indexing/tests of `geo_distance` native filter.
"""
return {
'lat': self.latitude,
'lon': self.longitude,
}
books/models/author.py
@python_2_unicode_compatible
class Author(models.Model):
"""Author."""
salutation = models.CharField(max_length=10)
name = models.CharField(max_length=200)
email = models.EmailField()
headshot = models.ImageField(upload_to='authors', null=True, blank=True)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return self.name
books/models/tag.py
class Tag(models.Model):
"""Simple tag model."""
title = models.CharField(max_length=255, unique=True)
class Meta(object):
"""Meta options."""
verbose_name = _("Tag")
verbose_name_plural = _("Tags")
def __str__(self):
return self.title
books/models/book.py
@python_2_unicode_compatible
class Book(models.Model):
"""Book."""
title = models.CharField(max_length=100)
description = models.TextField(null=True, blank=True)
summary = models.TextField(null=True, blank=True)
authors = models.ManyToManyField('books.Author', related_name='books')
publisher = models.ForeignKey(Publisher, related_name='books')
publication_date = models.DateField()
state = models.CharField(max_length=100,
choices=BOOK_PUBLISHING_STATUS_CHOICES,
default=BOOK_PUBLISHING_STATUS_DEFAULT)
isbn = models.CharField(max_length=100, unique=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
pages = models.PositiveIntegerField(default=200)
stock_count = models.PositiveIntegerField(default=30)
tags = models.ManyToManyField('books.Tag',
related_name='books',
blank=True)
class Meta(object):
"""Meta options."""
ordering = ["isbn"]
def __str__(self):
return self.title
@property
def publisher_indexing(self):
"""Publisher for indexing.
Used in Elasticsearch indexing.
"""
if self.publisher is not None:
return self.publisher.name
@property
def tags_indexing(self):
"""Tags for indexing.
Used in Elasticsearch indexing.
"""
return [tag.title for tag in self.tags.all()]
Sample document¶
Index definition¶
To separate dev/test/staging/production indexes, the following approach is recommended.
settings/base.py
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.book': 'book',
'search_indexes.documents.publisher': 'publisher',
}
settings/testing.py
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.book': 'test_book',
'search_indexes.documents.publisher': 'test_publisher',
}
settings/production.py
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.book': 'prod_book',
'search_indexes.documents.publisher': 'prod_publisher',
}
search_indexes/documents/book.py
from django.conf import settings
from django_elasticsearch_dsl import DocType, Index, fields
from elasticsearch_dsl import analyzer
from books.models import Book
# Name of the Elasticsearch index
INDEX = Index(settings.ELASTICSEARCH_INDEX_NAMES[__name__])
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
html_strip = analyzer(
'html_strip',
tokenizer="standard",
filter=["standard", "lowercase", "stop", "snowball"],
char_filter=["html_strip"]
)
@INDEX.doc_type
class BookDocument(DocType):
"""Book Elasticsearch document."""
id = fields.IntegerField(attr='id')
title = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
description = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
summary = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
publisher = fields.StringField(
attr='publisher_indexing',
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
publication_date = fields.DateField()
state = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
isbn = fields.StringField(
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword'),
}
)
price = fields.FloatField()
pages = fields.IntegerField()
stock_count = fields.IntegerField()
tags = fields.StringField(
attr='tags_indexing',
analyzer=html_strip,
fields={
'raw': fields.StringField(analyzer='keyword', multi=True),
'suggest': fields.CompletionField(multi=True),
},
multi=True
)
class Meta(object):
"""Meta options."""
model = Book # The model associate with this DocType
Sample serializer¶
search_indexes/serializers/tag.py
import json
from rest_framework import serializers
class TagSerializer(serializers.Serializer):
"""Helper serializer for the Tag field of the Book document."""
title = serializers.CharField()
class Meta(object):
"""Meta options."""
fields = ('title',)
read_only_fields = ('title',)
search_indexes/serializers/book.py
class BookDocumentSerializer(serializers.Serializer):
"""Serializer for the Book document."""
id = serializers.SerializerMethodField()
title = serializers.CharField(read_only=True)
description = serializers.CharField(read_only=True)
summary = serializers.CharField(read_only=True)
publisher = serializers.CharField(read_only=True)
publication_date = serializers.DateField(read_only=True)
state = serializers.CharField(read_only=True)
isbn = serializers.CharField(read_only=True)
price = serializers.FloatField(read_only=True)
pages = serializers.IntegerField(read_only=True)
stock_count = serializers.IntegerField(read_only=True)
tags = serializers.SerializerMethodField()
class Meta(object):
"""Meta options."""
fields = (
'id',
'title',
'description',
'summary',
'publisher',
'publication_date',
'state',
'isbn',
'price',
'pages',
'stock_count',
'tags',
)
read_only_fields = fields
def get_tags(self, obj):
"""Get tags."""
if obj.tags:
return list(obj.tags)
else:
return []
Sample view¶
search_indexes/viewsets/book.py
from django_elasticsearch_dsl_drf.constants import (
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_RANGE,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
)
from django_elasticsearch_dsl_drf.filter_backends import (
FilteringFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
# Example app models
from search_indexes.documents.book import BookDocument
from search_indxes.serializers import BookDocumentSerializer
class BookDocumentView(DocumentViewSet):
"""The BookDocument view."""
document = BookDocument
serializer_class = BookDocumentSerializer
lookup_field = 'id'
filter_backends = [
FilteringFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
]
# Define search fields
search_fields = (
'title',
'summary',
'description',
)
# Define filtering fields
filter_fields = {
'id': {
'field': '_id',
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_IN,
],
},
'publisher': 'publisher.raw',
'publication_date': 'publication_date',
'isbn': 'isbn.raw',
'tags': {
'field': 'tags',
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
'tags.raw': {
'field': 'tags.raw',
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
}
# Define ordering fields
ordering_fields = {
'id': 'id',
'title': 'title.raw',
'price': 'price.raw',
'state': 'state.raw',
'publication_date': 'publication_date',
}
# Specify default ordering
ordering = ('id', 'title',)
Usage example¶
Considering samples above, you should be able to perform the search, sorting and filtering actions described below.
Search¶
Query param name reserved for search is search
. Make sure your models and
documents do not have it as a field or attribute.
Multiple search terms are joined with OR
.
Let’s assume we have a number of Book items with fields title
,
description
and summary
.
Search in all fields
Search in all fields (title
, description
and summary
) for word
“education”.
http://127.0.0.1:8080/search/books/?search=education
Search a single term on specific field
In order to search in specific field (title
) for term “education”, add
the field name separated with :
to the search term.
http://127.0.0.1:8080/search/books/?search=title:education
Search for multiple terms
In order to search for multiple terms “education”, “technology” add
multiple search
query params.
http://127.0.0.1:8080/search/books/?search=education&search=technology
Search for multiple terms on specific fields
In order to search for multiple terms “education”, “technology” in specific
fields add multiple search
query params and field names separated with
:
to each of the search terms.
http://127.0.0.1:8080/search/books/?search=title:education&search=summary:technology
Search with boosting
It’s possible to boost search fields. In order to do that change the search_fields definition of the DocumentViewSet as follows:
class BookDocumentView(DocumentViewSet):
"""The BookDocument view."""
# ...
# Define search fields
search_fields = {
'title': {'boost': 4},
'summary': {'boost': 2},
'description': None,
}
# Order by `_score` first.
ordering = ('_score', 'id', 'title', 'price',)
# ...
Note, that we are ordering results by _score first.
Filtering¶
Let’s assume we have a number of Book documents with the tags (education, politics, economy, biology, climate, environment, internet, technology).
Multiple filter terms are joined with AND
.
Filter documents by field
Filter documents by field (state
) “published”.
http://127.0.0.1:8080/search/books/?state=published
Filter documents by multiple fields
Filter documents by field (states
) “published” and “in_progress”.
http://127.0.0.1:8080/search/books/?state__in=published__in_progress
Filter document by a single field
Filter documents by (field tag
) “education”.
http://127.0.0.1:8080/search/books/?tag=education
Filter documents by multiple fields
Filter documents by multiple fields (field tags
) “education” and “economy”
with use of functional in
query filter.
http://127.0.0.1:8080/search/books/?tags__in=education__economy
You can achieve the same effect by specifying multiple fields (tags
)
“education” and “economy”. Note, that in this case multiple filter terms are
joined with OR
.
http://127.0.0.1:8080/search/books/?tags=education&tags=economy
If you want the same as above, but joined with AND
, add __term
to each
lookup.
http://127.0.0.1:8080/search/books/?tags__term=education&tags__term=economy
Filter documents by a word part of a single field
Filter documents by a part word part in single field (tags
). Word part
should match both “technology” and “biology”.
http://127.0.0.1:8080/search/books/?tags__wildcard=*logy
Ordering¶
The -
prefix means ordering should be descending.
Order documents by field (ascending)
Order documents by field price
(ascending).
http://127.0.0.1:8080/search/books/?search=title:lorem&ordering=price
Order documents by field (descending)
Order documents by field price
(descending).
http://127.0.0.1:8080/search/books/?search=title:lorem&ordering=-price
Order documents by multiple fields
If you want to order by multiple fields, use multiple ordering query params. In
the example below, documents would be ordered first by field
publication_date
(descending), then by field price
(ascending).
http://127.0.0.1:8080/search/books/?search=title:lorem&ordering=-publication_date&ordering=price
Ids filter¶
Filters documents that only have the provided ids.
http://127.0.0.1:8000/api/articles/?ids=68__64__58
Or, alternatively:
http://127.0.0.1:8000/api/articles/?ids=68&ids=64&ids=58
Faceted search¶
In order to add faceted search support, we would have to extend our view set in the following way:
search_indexes/viewsets/book.py
# ...
from django_elasticsearch_dsl_drf.filter_backends import (
# ...
FacetedSearchFilterBackend,
)
# ...
from elasticsearch_dsl import (
DateHistogramFacet,
RangeFacet,
TermsFacet,
)
# ...
class BookDocumentView(DocumentViewSet):
"""The BookDocument view."""
# ...
filter_backends = [
# ...
FacetedSearchFilterBackend,
]
# ...
faceted_search_fields = {
'state': 'state.raw', # By default, TermsFacet is used
'publisher': {
'field': 'publisher.raw',
'facet': TermsFacet, # But we can define it explicitly
'enabled': True,
},
'publication_date': {
'field': 'publication_date',
'facet': DateHistogramFacet,
'options': {
'interval': 'year',
}
},
'pages_count': {
'field': 'pages',
'facet': RangeFacet,
'options': {
'ranges': [
("<10", (None, 10)),
("11-20", (11, 20)),
("20-50", (20, 50)),
(">50", (50, None)),
]
}
},
}
# ...
Note, that none of the facets is enabled by default, unless you explicitly specify it to be enabled. That means, that you will have to add a query string facet={facet_field_name} for each of the facets you want to see in results.
In the example below, we show results with faceted state
and
pages_count
facets.
http://127.0.0.1:8000/search/books/?facet=state&facet=pages_count
Post-filter¶
The post_filter is very similar to the common filter. The only difference is that it doesn’t affect facets. So, whatever post-filters applied, the numbers in facets will remain intact.
Sample view¶
Note
Note the PostFilterFilteringFilterBackend
and post_filter_fields
usage.
search_indexes/viewsets/book.py
# ...
from django_elasticsearch_dsl_drf.filter_backends import (
# ...
PostFilterFilteringFilterBackend,
)
# ...
class BookDocumentView(DocumentViewSet):
"""The BookDocument view."""
document = BookDocument
serializer_class = BookDocumentSerializer
lookup_field = 'id'
filter_backends = [
FilteringFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
PostFilterFilteringFilterBackend,
]
# Define search fields
search_fields = (
'title',
'summary',
'description',
)
# Define filtering fields
filter_fields = {
'id': {
'field': '_id',
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_IN,
],
},
'publisher': 'publisher.raw',
'publication_date': 'publication_date',
'isbn': 'isbn.raw',
'tags': {
'field': 'tags',
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
'tags.raw': {
'field': 'tags.raw',
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
}
# Define post-filter filtering fields
post_filter_fields = {
'publisher_pf': 'publisher.raw',
'isbn_pf': 'isbn.raw',
'state_pf': 'state.raw',
'tags_pf': {
'field': 'tags',
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
}
# Define ordering fields
ordering_fields = {
'id': 'id',
'title': 'title.raw',
'price': 'price.raw',
'state': 'state.raw',
'publication_date': 'publication_date',
}
# Specify default ordering
ordering = ('id', 'title',)
Sample queries¶
Filter documents by field
Filter documents by field (state
) “published”.
http://127.0.0.1:8080/search/books/?state_pf=published
Filter documents by multiple fields
Filter documents by field (states
) “published” and “in_progress”.
http://127.0.0.1:8080/search/books/?state_pf__in=published__in_progress
Geo-spatial features¶
For testing the boundaries the following online services might be helpful:
Filtering¶
Geo-distance filtering
Filter documents by radius of 100000km from the given location.
http://localhost:8000/search/publishers/?location__geo_distance=100000km__12.04__-63.93
Geo-polygon filtering
Filter documents that are located in the given polygon.
http://localhost:8000/search/publishers/?location__geo_polygon=40,-70__30,-80__20,-90
Geo-bounding-box filtering
Filter documents that are located in the given bounding box.
http://localhost:8000/search/publishers/?location__geo_bounding_box=44.87,40.07__43.87,41.11
Suggestions¶
The suggest feature suggests similar looking terms based on a provided text by using a suggester.
Note
The SuggesterFilterBackend
filter backend can be used in the
suggest
custom view action/route only. Usages outside of the are
suggest
action/route are restricted.
There are three options available here: term
, phrase
and
completion
.
Note
Suggestion functionality is exclusive. Once you have queried the
SuggesterFilterBackend
, the latter will transform your current
search query into suggestion search query (which is very different).
Therefore, always add it as the very last filter backend.
Completion suggesters¶
To make use of suggestions, you should properly index relevant fields of your
documents using fields.CompletionField
.
search_indexes/documents/publisher.py
from django.conf import settings
from django_elasticsearch_dsl import DocType, Index, fields
from books.models import Publisher
# Name of the Elasticsearch index
INDEX = Index(settings.ELASTICSEARCH_INDEX_NAMES[__name__])
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
@INDEX.doc_type
class PublisherDocument(DocType):
"""Publisher Elasticsearch document."""
id = fields.IntegerField(attr='id')
name = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
'suggest': fields.CompletionField(),
}
)
info = fields.StringField()
address = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword')
}
)
city = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
'suggest': fields.CompletionField(),
}
)
state_province = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
'suggest': fields.CompletionField(),
}
)
country = fields.StringField(
fields={
'raw': fields.StringField(analyzer='keyword'),
'suggest': fields.CompletionField(),
}
)
website = fields.StringField()
# Location
location = fields.GeoPointField(attr='location_field_indexing')
class Meta(object):
"""Meta options."""
model = Publisher # The model associate with this DocType
After that the name.suggest
, city.suggest
, state_province.suggest
and country.suggest
fields would be available for suggestions feature.
This is how publisher serializer would look like.
search_indexes/serializers/publisher.py
import json
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
class PublisherDocumentSerializer(DocumentSerializer):
"""Serializer for Publisher document."""
class Meta(object):
"""Meta options."""
# Note, that since we're using a dynamic serializer,
# we only have to declare fields that we want to be shown. If
# somehow, dynamic serializer doesn't work for you, either extend
# or declare your serializer explicitly.
fields = (
'id',
'name',
'info',
'address',
'city',
'state_province',
'country',
'website',
)
In order to add suggestions support, we would have to extend our view set in the following way:
search_indexes/viewsets/publisher.py
# ...
from django_elasticsearch_dsl_drf.constants import SUGGESTER_COMPLETION
from django_elasticsearch_dsl_drf.filter_backends import (
# ...
SuggesterFilterBackend,
)
# ...
class PublisherDocumentViewSet(DocumentViewSet):
"""The PublisherDocument view."""
document = PublisherDocument
# ...
filter_backends = [
# ...
SuggesterFilterBackend,
]
# ...
# Suggester fields
suggester_fields = {
'name_suggest': {
'field': 'name.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
'options': {
'size': 20, # Override default number of suggestions
},
},
'city_suggest': {
'field': 'city.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
},
'state_province_suggest': {
'field': 'state_province.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
},
'country_suggest': {
'field': 'country.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
},
}
# Geo-spatial filtering fields
geo_spatial_filter_fields = {
'location': {
'lookups': [
LOOKUP_FILTER_GEO_DISTANCE,
],
},
}
In the example below, we show suggestion results (auto-completion) for
country
field.
Once you have extended your view set with SuggesterFilterBackend
functionality, you can make use of the suggest
custom action of your
view set.
Request
GET http://127.0.0.1:8000/search/publishers/suggest/?country_suggest__completion=Ar
Response
{
"_shards": {
"failed": 0,
"successful": 1,
"total": 1
},
"country_suggest__completion": [
{
"options": [
{
"score": 1.0,
"text": "Armenia"
},
{
"score": 1.0,
"text": "Argentina"
}
],
"offset": 0,
"length": 2,
"text": "Ar"
}
]
}
You can also have multiple suggesters per request.
Request
GET http://127.0.0.1:8000/search/publishers/suggest/?name_suggest__completion=B&country_suggest__completion=Ar
Response
{
"_shards": {
"successful": 1,
"total": 1,
"failed": 0
},
"country_suggest__completion": [
{
"text": "Ar",
"options": [
{
"score": 1.0,
"text": "Armenia"
},
{
"score": 1.0,
"text": "Argentina"
}
],
"offset": 0,
"length": 2
}
],
"name_suggest__completion": [
{
"text": "B",
"options": [
{
"score": 1.0,
"text": "Book Works"
},
{
"score": 1.0,
"text": "Brumleve LLC"
},
{
"score": 1.0,
"text": "Booktrope"
},
{
"score": 1.0,
"text": "Borman, Post and Wendt"
},
{
"score": 1.0,
"text": "Book League of America"
}
],
"offset": 0,
"length": 1
}
]
}
Suggestions on Array/List fields (typical use case - tags, where Tag model would be a many-to-many relation to a Book model) work almost the same.
Before checking the Sample requests/responses, do have in mind the following:
Book
(see the Sample models)BookSerializer
(see the Sample serializer)BookDocumentView
(see the `Sample view`_)
Once you have extended your view set with SuggesterFilterBackend
functionality, you can make use of the suggest
custom action of your
view set.
Request
GET http://127.0.0.1:8000/search/books/suggest/?tag_suggest__completion=bio
Response
{
"_shards": {
"failed": 0,
"successful": 1,
"total": 1
},
"country_suggest__completion": [
{
"options": [
{
"score": 1.0,
"text": "Biography"
},
{
"score": 1.0,
"text": "Biology"
}
],
"offset": 0,
"length": 2,
"text": "bio"
}
]
}
Note, that context suggesters only work for completion (thus, not for term or phrase).
The completion suggester considers all documents in the index, but it is often desirable to serve suggestions filtered and/or boosted by some criteria. For example, you want to suggest song titles filtered by certain artists or you want to boost song titles based on their genre.
In that case, the document definition should be altered as follows:
Document definition
class BookDocument(DocType):
# ...
title = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
'suggest_context': fields.CompletionField(
contexts=[
{
"name": "tag",
"type": "category",
# The `path` value shall be pointing to an
# existing field of current document, which shall
# be used for filtering.
"path": "tags.raw",
},
]
),
}
)
# Tags
tags = StringField(
attr='tags_indexing',
analyzer=html_strip,
fields={
'raw': KeywordField(multi=True),
'suggest': fields.CompletionField(multi=True),
},
multi=True
)
# ...
ViewSet should altered as follows:
ViewSet definition
class BookFrontendDocumentViewSet(DocumentViewSet):
# ...
# Suggester fields
suggester_fields = {
'title_suggest_context': {
'field': 'title.suggest_context',
'default_suggester': SUGGESTER_COMPLETION,
# We want to be able to filter the completion filter
# results on the following params: tag, state and publisher.
# We also want to provide the size value.
# See the "https://www.elastic.co/guide/en/elasticsearch/
# reference/6.1/suggester-context.html" for the reference.
'completion_options': {
'category_filters': {
# The `tag` has been defined as `name` value in the
# `suggest_context` of the `BookDocument`.
'title_suggest_tag': 'tag',
},
},
'options': {
'size': 10, # By default, number of results is 5.
},
},
}
# ...
And finally we can narrow our suggestions as follows:
Sample request
In the example below we have filtered suggestions by tags “Art” and “Comics” having boosted “Comics” by 2.0.
GET http://localhost:8000/search/books-frontend/suggest/?title_suggest_context=M&title_suggest_tag=Art&title_suggest_tag=Comics__2.0
Geo context allows to get suggestions within a certain distance from a specified geo location.
In that case, the document definition should be altered as follows:
Document definition
class AddressDocument(DocType):
# ...
street = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
'suggest_context': fields.CompletionField(
contexts=[
{
"name": "loc",
"type": "geo",
"path": "location",
# You could also optionally add precision value.
# However, this is not required and can be
# specified in the query during runtime.
# "precision": "100km",
},
],
),
}
)
location = fields.GeoPointField(
attr='location_field_indexing',
)
# ...
ViewSet should altered as follows:
ViewSet definition
class BookFrontendDocumentViewSet(DocumentViewSet):
# ...
# Suggester fields
suggester_fields = {
'street_suggest_context': {
'field': 'street.suggest_context',
'default_suggester': SUGGESTER_COMPLETION,
# We want to be able to filter the completion filter
# results on the following params: tag, state and publisher.
# We also want to provide the size value.
# See the "https://www.elastic.co/guide/en/elasticsearch/
# reference/6.1/suggester-context.html" for the reference.
'completion_options': {
'geo_filters': {
'title_suggest_loc': 'loc',
},
},
'options': {
'size': 10, # By default, number of results is 5.
},
},
}
# ...
And finally we can narrow our suggestions as follows:
Sample request
In the example below we have filtered suggestions within 8000km distance from geo-point (-30, -100).
GET http://localhost:8000/search/addresses-frontend/suggest/?street_suggest_context=L&title_suggest_loc=-30__-100__8000km
Same query with boosting (boost value 2.0):
GET http://localhost:8000/search/addresses-frontend/suggest/?street_suggest_context=L&title_suggest_loc=-30__-100__8000km__2.0
Term and Phrase suggestions¶
While for the completion
suggesters to work the CompletionField
shall
be used, the term
and phrase
suggesters work on common text fields.
search_indexes/documents/book.py
from django.conf import settings
from django_elasticsearch_dsl import DocType, Index, fields
from books.models import Book
# Name of the Elasticsearch index
INDEX = Index(settings.ELASTICSEARCH_INDEX_NAMES[__name__])
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
@INDEX.doc_type
class BookDocument(DocType):
"""Book Elasticsearch document."""
# ID
id = fields.IntegerField(attr='id')
title = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
)
description = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
}
)
summary = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField()
}
)
# Publisher
publisher = StringField(
attr='publisher_indexing',
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
)
# Publication date
publication_date = fields.DateField()
# State
state = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
}
)
# ISBN
isbn = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
}
)
# Price
price = fields.FloatField()
# Pages
pages = fields.IntegerField()
# Stock count
stock_count = fields.IntegerField()
# Tags
tags = StringField(
attr='tags_indexing',
analyzer=html_strip,
fields={
'raw': KeywordField(multi=True),
'suggest': fields.CompletionField(multi=True),
},
multi=True
)
null_field = fields.StringField(attr='null_field_indexing')
class Meta(object):
"""Meta options."""
model = Book # The model associate with this DocType
Note
The suggester filter backends shall come as last ones.
Suggesters for the view are configured in suggester_fields
property.
In the example below, the title_suggest
is the name of the GET query param
which points to the title.suggest
field of the BookDocument
document.
For the title_suggest
the allowed suggesters are SUGGESTER_COMPLETION
,
SUGGESTER_TERM
and SUGGESTER_PHRASE
.
URL shall be constructed in the following way:
/search/books/suggest/?{QUERY_PARAM}__{SUGGESTER_NAME}={VALUE}
Example for completion
suggester:
GET http://127.0.0.1:8000/search/books/suggest/?title_suggest__completion=temp
However, since we have default_suggester
defined we can skip the
__{SUGGESTER_NAME}
part (if we want completion
suggester
functionality). Thus, it might be written as short as:
GET http://127.0.0.1:8000/search/books/suggest/?title_suggest=temp
Example for term
suggester:
GET http://127.0.0.1:8000/search/books/suggest/?title_suggest__term=tmeporus
Example for phrase
suggester:
GET http://127.0.0.1:8000/search/books/suggest/?title_suggest__phrase=tmeporus
search_indexes/viewsets/book.py
from django_elasticsearch_dsl_drf.constants import (
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_RANGE,
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_EXCLUDE,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_ISNULL,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
SUGGESTER_COMPLETION,
SUGGESTER_PHRASE,
SUGGESTER_TERM,
)
from django_elasticsearch_dsl_drf.filter_backends import (
# ...
SuggesterFilterBackend,
)
class BookDocumentViewSet(DocumentViewSet):
"""The BookDocument view."""
document = BookDocument
# serializer_class = BookDocumentSerializer
serializer_class = BookDocumentSimpleSerializer
lookup_field = 'id'
filter_backends = [
FilteringFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
SuggesterFilterBackend, # This should be the last backend
]
# Define search fields
search_fields = (
'title',
'description',
'summary',
)
# Define filter fields
filter_fields = {
'id': {
'field': 'id',
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
LOOKUP_FILTER_TERMS,
],
},
'title': 'title.raw',
'publisher': 'publisher.raw',
'publication_date': 'publication_date',
'state': 'state.raw',
'isbn': 'isbn.raw',
'price': {
'field': 'price.raw',
'lookups': [
LOOKUP_FILTER_RANGE,
],
},
'pages': {
'field': 'pages',
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'stock_count': {
# 'field': 'stock_count',
'lookups': [
LOOKUP_FILTER_RANGE,
LOOKUP_QUERY_GT,
LOOKUP_QUERY_GTE,
LOOKUP_QUERY_LT,
LOOKUP_QUERY_LTE,
],
},
'tags': {
'field': 'tags',
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
LOOKUP_QUERY_ISNULL,
],
},
'tags.raw': {
'field': 'tags.raw',
'lookups': [
LOOKUP_FILTER_TERMS,
LOOKUP_FILTER_PREFIX,
LOOKUP_FILTER_WILDCARD,
LOOKUP_QUERY_IN,
LOOKUP_QUERY_EXCLUDE,
],
},
# This has been added to test `exists` filter.
'non_existent_field': 'non_existent_field',
# This has been added to test `isnull` filter.
'null_field': 'null_field',
}
# Define ordering fields
ordering_fields = {
'id': 'id',
'title': 'title.raw',
'price': 'price.raw',
'state': 'state.raw',
'publication_date': 'publication_date',
}
# Specify default ordering
ordering = ('id', 'title', 'price',)
# Suggester fields
suggester_fields = {
'title_suggest': {
'field': 'title.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
SUGGESTER_TERM,
SUGGESTER_PHRASE,
]
'default_suggester': SUGGESTER_COMPLETION,
'options': {
'size': 10, # Number of suggestions to retrieve.
},
},
'publisher_suggest': 'publisher.suggest',
'tag_suggest': 'tags.suggest',
'summary_suggest': 'summary',
}
Note, that by default the number of suggestions is limited to 5. If you need more suggestions, add ‘options` dictionary with size provided, as show above.
Once you have extended your view set with SuggesterFilterBackend
functionality, you can make use of the suggest
custom action of your
view set.
Let’s considering, that one of our books has the following text in the summary:
Twas brillig, and the slithy toves
Did gyre and gimble in the wabe.
All mimsy were the borogoves
And the mome raths outgrabe.
"Beware the Jabberwock, my son!
The jaws that bite, the claws that catch!
Beware the Jubjub bird, and shun
The frumious Bandersnatch!"
He took his vorpal sword in his hand,
Long time the manxome foe he sought --
So rested he by the Tumtum tree,
And stood awhile in thought.
Request
GET http://127.0.0.1:8000/search/books/suggest/?title_suggest__completion=temp
Response
{
"_shards": {
"successful": 1,
"total": 1,
"failed": 0
},
"title_suggest": [
{
"length": 4,
"text": "temp",
"options": [
{
"text": "Tempora voluptates distinctio facere ",
"_index": "book",
"_score": 1.0,
"_id": "1000087",
"_type": "book_document",
"_source": {
"description": null,
"summary": "Veniam dolores recusandae maxime laborum earum.",
"id": 1000087,
"state": "cancelled",
"authors": [
"Jayden van Luyssel",
"Yassin van Rooij",
"Florian van 't Erve",
"Mats van Nimwegen",
"Wessel Keltenie"
],
"title": "Tempora voluptates distinctio facere."
}
},
{
"text": "Tempore sapiente repellat alias ad corrupti",
"_index": "book",
"_score": 1.0,
"_id": "29",
"_type": "book_document"
"_source": {
"description": null,
"summary": "Dolores minus architecto iure fugit qui sed.",
"id": 29,
"state": "canelled",
"authors": [
"Wout van Northeim",
"Lenn van Vliet-Kuijpers",
"Tijs Mulder"
],
"title": "Tempore sapiente repellat alias ad."
},
},
{
"text": "Temporibus exercitationem minus expedita",
"_index": "book",
"_score": 1.0,
"_id": "17",
"_type": "book_document",
"_source": {
"description": null,
"summary": "A laborum alias voluptates tenetur sapiente modi.",
"id": 17,
"state": "canelled",
"authors": [
"Juliette Estey",
"Keano de Keijzer",
"Koen Scheffers",
"Florian van 't Erve",
"Tara Oversteeg",
"Mats van Nimwegen"
],
"title": "Temporibus exercitationem minus expedita."
}
}
],
"offset": 0
}
]
}
Request
GET http://127.0.0.1:8000/search/books/suggest/?summary_suggest__term=tovse
Response
{
"_shards": {
"failed": 0,
"total": 1,
"successful": 1
},
"summary_suggest__term": [
{
"text": "tovs",
"offset": 0,
"options": [
{
"text": "tove",
"score": 0.75,
"freq": 1
},
{
"text": "took",
"score": 0.5,
"freq": 1
},
{
"text": "twas",
"score": 0.5,
"freq": 1
}
],
"length": 5
}
]
}
Request
GET http://127.0.0.1:8000/search/books/suggest/?summary_suggest__phrase=slith%20tovs
Response
{
"summary_suggest__phrase": [
{
"text": "slith tovs",
"offset": 0,
"options": [
{
"text": "slithi tov",
"score": 0.00083028956
}
],
"length": 10
}
],
"_shards": {
"failed": 0,
"total": 1,
"successful": 1
}
}
Functional suggestions¶
If native suggestions are not good enough for you, use functional suggesters.
Configuration is very similar to native suggesters.
Document definition¶
Obviously, different filters require different approaches. For instance, when using functional completion prefix filter, the best approach is to use keyword field of the Elasticsearch. While for match completion, Ngram fields work really well.
The following example indicates Ngram analyzer/filter usage.
search_indexes/documents/book.py
from django.conf import settings
from django_elasticsearch_dsl import DocType, Index, fields
from elasticsearch_dsl import analyzer
from elasticsearch_dsl.analysis import token_filter
from books.models import Book
edge_ngram_completion_filter = token_filter(
'edge_ngram_completion_filter',
type="edge_ngram",
min_gram=1,
max_gram=20
)
edge_ngram_completion = analyzer(
"edge_ngram_completion",
tokenizer="standard",
filter=["lowercase", edge_ngram_completion_filter]
)
INDEX = Index(settings.ELASTICSEARCH_INDEX_NAMES[__name__])
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
@INDEX.doc_type
class BookDocument(DocType):
"""Book Elasticsearch document."""
# In different parts of the code different fields are used. There are
# a couple of use cases: (1) more-like-this functionality, where `title`,
# `description` and `summary` fields are used, (2) search and filtering
# functionality where all of the fields are used.
# ID
id = fields.IntegerField(attr='id')
# ********************************************************************
# *********************** Main data fields for search ****************
# ********************************************************************
title = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
'edge_ngram_completion': StringField(
analyzer=edge_ngram_completion
),
}
)
# ...
class Meta(object):
"""Meta options."""
model = Book # The model associate with this DocType
ViewSet definition¶
Note
The suggester filter backends shall come as last ones.
Functional suggesters for the view are configured in
functional_suggester_fields
property.
In the example below, the title_suggest
is the name of the GET query
param which points to the title.raw
field of the BookDocument
document.
For the title_suggest
the allowed suggester is
FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX
. For Ngram match we have the
title_suggest_match
field, which points to title.edge_ngram_completion
field of the same document. For title_suggest_match
the allowed suggester
is FUNCTIONAL_SUGGESTER_COMPLETION_MATCH
.
URL shall be constructed in the following way:
/search/books/functional_suggest/?{QUERY_PARAM}__{SUGGESTER_NAME}={VALUE}
Example for completion_prefix
suggester:
GET http://localhost:8000/search/books/functional_suggest/?title_suggest_prefix__completion_prefix=Temp
However, since we have default_suggester
defined we can skip the
__{SUGGESTER_NAME}
part (if we want completion_prefix
suggester
functionality). Thus, it might be written as short as:
GET http://localhost:8000/search/books/functional_suggest/?title_suggest_prefix=Temp
Example for completion_match
suggester:
GET http://localhost:8000/search/books/functional_suggest/?title_suggest_match__completion_match=Temp
However, since we have default_suggester
defined we can skip the
__{SUGGESTER_NAME}
part (if we want completion_match
suggester
functionality). Thus, it might be written as short as:
GET http://localhost:8000/search/books/functional_suggest/?title_suggest_match=Temp
search_indexes/viewsets/book.py
from django_elasticsearch_dsl_drf.constants import (
# ...
FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX,
FUNCTIONAL_SUGGESTER_COMPLETION_MATCH,
)
from django_elasticsearch_dsl_drf.filter_backends import (
# ...
SuggesterFilterBackend,
)
class BookDocumentViewSet(DocumentViewSet):
"""The BookDocument view."""
document = BookDocument
serializer_class = BookDocumentSerializer
lookup_field = 'id'
filter_backends = [
FilteringFilterBackend,
IdsFilterBackend,
OrderingFilterBackend,
DefaultOrderingFilterBackend,
SearchFilterBackend,
FacetedSearchFilterBackend,
HighlightBackend,
FunctionalSuggesterFilterBackend, # This should come as last
]
# ...
# Functional suggester fields
functional_suggester_fields = {
'title_suggest': {
'field': 'title.raw',
'suggesters': [
FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX,
],
'default_suggester': FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX,
'options': {
'size': 25,
'from': 0,
}
},
'title_suggest_match': {
'field': 'title.edge_ngram_completion',
'suggesters': [FUNCTIONAL_SUGGESTER_COMPLETION_MATCH],
'default_suggester': FUNCTIONAL_SUGGESTER_COMPLETION_MATCH,
}
}
Note
Note, that in functional_suggester_fields['title_suggest']['options']
there are two params: size
and from
. They control the query size
and the offset of the generated functional suggest query.
Highlighting¶
Highlighters enable you to get highlighted snippets from one or more fields in your search results so you can show users where the query matches are.
ViewSet definition
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from django_elasticsearch_dsl_drf.filter_backends import (
# ...
HighlightBackend,
)
from ..documents import BookDocument
from ..serializers import BookDocumentSimpleSerializer
class BookDocumentViewSet(BaseDocumentViewSet):
"""The BookDocument view."""
document = BookDocument
# serializer_class = BookDocumentSerializer
serializer_class = BookDocumentSimpleSerializer
lookup_field = 'id'
filter_backends = [
# ...
HighlightBackend,
]
# ...
# Define highlight fields
highlight_fields = {
'title': {
'enabled': True,
'options': {
'pre_tags': ["<b>"],
'post_tags': ["</b>"],
}
},
'summary': {
'options': {
'fragment_size': 50,
'number_of_fragments': 3
}
},
'description': {},
}
# ...
Request
GET http://127.0.0.1:8000/search/books/?search=optimisation&highlight=title&highlight=summary
Response
{
"count": 1,
"next": null,
"previous": null,
"facets": {
"_filter_publisher": {
"publisher": {
"buckets": [
{
"key": "Self published",
"doc_count": 1
}
],
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0
},
"doc_count": 1
}
},
"results": [
{
"id": 999999,
"title": "Performance optimisation",
"description": null,
"summary": "Ad animi adipisci libero facilis iure totam
impedit. Facilis maiores quae qui magnam dolores.
Veritatis quia amet porro voluptates iure quod
impedit. Dolor voluptatibus maiores at libero
magnam.",
"authors": [
"Artur Barseghyan"
],
"publisher": "Self published",
"publication_date": "1981-04-29",
"state": "cancelled",
"isbn": "978-1-7372176-0-2",
"price": 40.51,
"pages": 162,
"stock_count": 30,
"tags": [
"Guide",
"Poetry",
"Fantasy"
],
"highlight": {
"title": [
"Performance <b>optimisation</b>"
]
},
"null_field": null
}
]
}
Pagination¶
Page number pagination¶
By default, the PageNumberPagination
class is used on all view sets
which inherit from DocumentViewSet
.
Example:
http://127.0.0.1:8000/search/books/?page=4
http://127.0.0.1:8000/search/books/?page=4&page_size=100
Limit/offset pagination¶
In order to use a different pagination_class
, for instance the
LimitOffsetPagination
, specify it explicitly in the view.
search_indexes/viewsets/book.py
# ...
from django_elasticsearch_dsl_drf.pagination import LimitOffsetPagination
# ...
class BookDocumentView(DocumentViewSet):
"""The BookDocument view."""
# ...
pagination_class = LimitOffsetPagination
# ...
Example:
http://127.0.0.1:8000/search/books/?limit=100
http://127.0.0.1:8000/search/books/?offset=400&limit=100
Customisations¶
If you want to add additional data to the paginated response, for instance,
the page size, subclass the correspondent pagination class and add your
modifications in the get_paginated_response_context
method as follows:
from django_elasticsearch_dsl_drf.pagination import PageNumberPagination
class CustomPageNumberPagination(PageNumberPagination):
"""Custom page number pagination."""
def get_paginated_response_context(self, data):
__data = super(
CustomPageNumberPagination,
self
).get_paginated_response_context(data)
__data.append(
('current_page', int(self.request.query_params.get('page', 1)))
)
__data.append(
('page_size', self.get_page_size(self.request))
)
return sorted(__data)
Same applies to the customisations of the LimitOffsetPagination
.
Nested fields usage examples¶
Advanced Django REST framework integration examples with object/nested fields.
See the example project for sample models/views/serializers.
Contents:
Table of Contents
Example app¶
Sample models¶
books/models/continent.py
from django.db import models
from six import python_2_unicode_compatible
@python_2_unicode_compatible
class Continent(models.Model):
"""Continent."""
name = models.CharField(max_length=255)
info = models.TextField(null=True, blank=True)
latitude = models.DecimalField(
null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0
)
longitude = models.DecimalField(
null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0
)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return self.name
@property
def location_field_indexing(self):
"""Location for indexing.
Used in Elasticsearch indexing/tests of `geo_distance` native filter.
"""
return {
'lat': self.latitude,
'lon': self.longitude,
}
books/models/country.py
@python_2_unicode_compatible
class Country(models.Model):
"""Country."""
name = models.CharField(max_length=255)
info = models.TextField(null=True, blank=True)
continent = models.ForeignKey(
'books.Continent',
on_delete=models.CASCADE
)
latitude = models.DecimalField(
null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0
)
longitude = models.DecimalField(
null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0
)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return self.name
@property
def location_field_indexing(self):
"""Location for indexing.
Used in Elasticsearch indexing/tests of `geo_distance` native
filter.
"""
return {
'lat': self.latitude,
'lon': self.longitude,
}
books/models/city.py
@python_2_unicode_compatible
class City(models.Model):
"""City."""
name = models.CharField(max_length=255)
info = models.TextField(null=True, blank=True)
country = models.ForeignKey('books.Country', on_delete=models.CASCADE)
latitude = models.DecimalField(
null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0
)
longitude = models.DecimalField(
null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0
)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return self.name
@property
def location_field_indexing(self):
"""Location for indexing.
Used in Elasticsearch indexing/tests of `geo_distance` native
filter.
"""
return {
'lat': self.latitude,
'lon': self.longitude,
}
books/models/address.py
from django.db import models
from django_elasticsearch_dsl_drf.wrappers import dict_to_obj
from six import python_2_unicode_compatible
@python_2_unicode_compatible
class Address(models.Model):
"""Address."""
street = models.CharField(max_length=255)
house_number = models.CharField(max_length=60)
appendix = models.CharField(max_length=30, null=True, blank=True)
zip_code = models.CharField(max_length=60)
city = models.ForeignKey('books.City', on_delete=models.CASCADE)
latitude = models.DecimalField(
null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0
)
longitude = models.DecimalField(
null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0
)
class Meta(object):
"""Meta options."""
ordering = ["id"]
def __str__(self):
return "{} {} {} {}".format(
self.street,
self.house_number,
self.appendix,
self.zip_code
)
@property
def location_field_indexing(self):
"""Location for indexing.
Used in Elasticsearch indexing/tests of `geo_distance` native
filter.
"""
return {
'lat': self.latitude,
'lon': self.longitude,
}
@property
def country_indexing(self):
"""Country data (nested) for indexing.
Example:
>>> mapping = {
>>> 'country': {
>>> 'name': 'Netherlands',
>>> 'city': {
>>> 'name': 'Amsterdam',
>>> }
>>> }
>>> }
:return:
"""
wrapper = dict_to_obj({
'name': self.city.country.name,
'city': {
'name': self.city.name
}
})
return wrapper
@property
def continent_indexing(self):
"""Continent data (nested) for indexing.
Example:
>>> mapping = {
>>> 'continent': {
>>> 'name': 'Asia',
>>> 'country': {
>>> 'name': 'Netherlands',
>>> 'city': {
>>> 'name': 'Amsterdam',
>>> }
>>> }
>>> }
>>> }
:return:
"""
wrapper = dict_to_obj({
'name': self.city.country.continent.name,
'country': {
'name': self.city.country.name,
'city': {
'name': self.city.name,
}
}
})
return wrapper
Sample document¶
Index definition¶
To separate dev/test/staging/production indexes, the following approach is recommended.
settings/base.py
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.address': 'address',
}
settings/testing.py
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.address': 'test_address',
}
settings/production.py
# Name of the Elasticsearch index
ELASTICSEARCH_INDEX_NAMES = {
'search_indexes.documents.address': 'prod_address',
}
search_indexes/documents/address.py
from django.conf import settings
from django_elasticsearch_dsl import DocType, Index, fields
from django_elasticsearch_dsl_drf.compat import KeywordField, StringField
from books.models import Address
from .analyzers import html_strip
INDEX = Index(settings.ELASTICSEARCH_INDEX_NAMES[__name__])
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
@INDEX.doc_type
class AddressDocument(DocType):
"""Address Elasticsearch document."""
# In different parts of the code different fields are used. There are
# a couple of use cases: (1) more-like-this functionality, where `title`,
# `description` and `summary` fields are used, (2) search and filtering
# functionality where all of the fields are used.
# ID
id = fields.IntegerField(attr='id')
# ********************************************************************
# *********************** Main data fields for search ****************
# ********************************************************************
street = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
)
house_number = StringField(analyzer=html_strip)
appendix = StringField(analyzer=html_strip)
zip_code = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
)
# ********************************************************************
# ********** Additional fields for search and filtering **************
# ********************************************************************
# City object
city = fields.ObjectField(
properties={
'name': StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
),
'info': StringField(analyzer=html_strip),
'location': fields.GeoPointField(attr='location_field_indexing'),
'country': fields.ObjectField(
properties={
'name': StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
),
'info': StringField(analyzer=html_strip),
'location': fields.GeoPointField(
attr='location_field_indexing'
)
}
)
}
)
# Country object
country = fields.NestedField(
attr='country_indexing',
properties={
'name': StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
),
'city': fields.ObjectField(
properties={
'name': StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
},
),
},
),
},
)
# Continent object
continent = fields.NestedField(
attr='continent_indexing',
properties={
'name': StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
),
'country': fields.NestedField(
properties={
'name': StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
}
),
'city': fields.NestedField(
properties={
'name': StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
}
)
}
)
}
)
}
)
location = fields.GeoPointField(attr='location_field_indexing')
class Meta(object):
"""Meta options."""
model = Address # The model associate with this DocType
Sample serializer¶
search_indexes/serializers/address.py
from django_elasticsearch_dsl_drf.serializers import DocumentSerializer
from ..documents import AddressDocument
class AddressDocumentSerializer(DocumentSerializer):
"""Serializer for address document."""
class Meta(object):
"""Meta options."""
document = AddressDocument
fields = (
'id',
'street',
'house_number',
'appendix',
'zip_code',
'city',
'country',
'continent',
'location',
)
Sample view¶
search_indexes/viewsets/address.py
from django_elasticsearch_dsl_drf.constants import (
LOOKUP_FILTER_GEO_DISTANCE,
LOOKUP_FILTER_GEO_POLYGON,
LOOKUP_FILTER_GEO_BOUNDING_BOX,
SUGGESTER_COMPLETION,
)
from django_elasticsearch_dsl_drf.filter_backends import (
DefaultOrderingFilterBackend,
FacetedSearchFilterBackend,
FilteringFilterBackend,
GeoSpatialFilteringFilterBackend,
GeoSpatialOrderingFilterBackend,
NestedFilteringFilterBackend,
OrderingFilterBackend,
SearchFilterBackend,
SuggesterFilterBackend,
)
from django_elasticsearch_dsl_drf.pagination import LimitOffsetPagination
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from ..documents import AddressDocument
from ..serializers import AddressDocumentSerializer
class AddressDocumentViewSet(DocumentViewSet):
"""The AddressDocument view."""
document = AddressDocument
serializer_class = AddressDocumentSerializer
lookup_field = 'id'
filter_backends = [
FacetedSearchFilterBackend,
FilteringFilterBackend,
OrderingFilterBackend,
SearchFilterBackend,
GeoSpatialFilteringFilterBackend,
GeoSpatialOrderingFilterBackend,
NestedFilteringFilterBackend,
DefaultOrderingFilterBackend,
SuggesterFilterBackend,
]
pagination_class = LimitOffsetPagination
# Define search fields
search_fields = (
'street',
'zip_code',
'city.name',
'city.country.name',
)
# Define filtering fields
filter_fields = {
'id': None,
'city': 'city.name.raw',
}
# Nested filtering fields
nested_filter_fields = {
'continent_country': {
'field': 'continent.country.name.raw',
'path': 'continent.country',
},
'continent_country_city': {
'field': 'continent.country.city.name.raw',
'path': 'continent.country.city',
},
}
# Define geo-spatial filtering fields
geo_spatial_filter_fields = {
'location': {
'lookups': [
LOOKUP_FILTER_GEO_BOUNDING_BOX,
LOOKUP_FILTER_GEO_DISTANCE,
LOOKUP_FILTER_GEO_POLYGON,
],
},
}
# Define ordering fields
ordering_fields = {
'id': None,
'street': None,
'city': 'city.name.raw',
'country': 'city.country.name.raw',
'zip_code': None,
}
# Define ordering fields
geo_spatial_ordering_fields = {
'location': None,
}
# Specify default ordering
ordering = (
'id',
'street.raw',
'city.name.raw',
)
# Suggester fields
suggester_fields = {
'street_suggest': {
'field': 'street.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
},
'city_suggest': {
'field': 'city.name.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
},
'country_suggest': {
'field': 'city.country.name.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
}
}
# Facets
faceted_search_fields = {
'city': {
'field': 'city.name.raw',
'enabled': True,
},
'country': {
'field': 'city.country.name.raw',
'enabled': True,
},
}
Usage example¶
Considering samples above, you should be able to perform the search, sorting and filtering actions described below.
Sample queries¶
Just a couple of examples, because searching in nested fields doesn’t differ from searching in simple fields.
Search in all fields
Search in all fields (street
, zip_code
and city
, country
) for
word “Picadilly”.
http://127.0.0.1:8000/search/addresses/?search=Piccadilly
Search a single term on specific field
In order to search in specific field (country
) for term “Armenia”, add
the field name separated with |
to the search term.
http://127.0.0.1:8000/search/addresses/?search=city.country.name:Armenia
Filter documents by nested field
Filter documents by field (continent.country
) “Armenia”.
http://127.0.0.1:8000/search/addresses/?continent_country=Armenia
Filter documents by field (continent.country.city
) “Amsterdam”.
http://127.0.0.1:8000/search/addresses/?continent_country_city=Amsterdam
For nested search, let’s have another example.
books/models/city.py
from django.db import models
from six import python_2_unicode_compatible
@python_2_unicode_compatible
class City(models.Model):
"""City."""
name = models.CharField(max_length=255)
info = models.TextField(null=True, blank=True)
country = models.ForeignKey('books.Country')
latitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
longitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
books/models/country.py
from django.db import models
from six import python_2_unicode_compatible
@python_2_unicode_compatible
class Country(models.Model):
"""Country."""
name = models.CharField(max_length=255)
info = models.TextField(null=True, blank=True)
latitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
longitude = models.DecimalField(null=True,
blank=True,
decimal_places=15,
max_digits=19,
default=0)
documents/city.py
from django.conf import settings
from django_elasticsearch_dsl import DocType, Index, fields
from django_elasticsearch_dsl_drf.compat import KeywordField, StringField
from books.models import City
from .analyzers import html_strip
INDEX = Index(settings.ELASTICSEARCH_INDEX_NAMES[__name__])
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1
)
@INDEX.doc_type
class CityDocument(DocType):
"""City Elasticsearch document.
This document has been created purely for testing out complex fields.
"""
# ID
id = fields.IntegerField(attr='id')
# ********************************************************************
# ********************** Main data fields for search *****************
# ********************************************************************
name = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
)
info = StringField(analyzer=html_strip)
# ********************************************************************
# ************** Nested fields for search and filtering **************
# ********************************************************************
# City object
country = fields.NestedField(
properties={
'name': StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
}
),
'info': StringField(analyzer=html_strip),
'location': fields.GeoPointField(attr='location_field_indexing'),
}
)
location = fields.GeoPointField(attr='location_field_indexing')
# ********************************************************************
# ********** Other complex fields for search and filtering ***********
# ********************************************************************
boolean_list = fields.ListField(
StringField(attr='boolean_list_indexing')
)
datetime_list = fields.ListField(
StringField(attr='datetime_list_indexing')
)
float_list = fields.ListField(
StringField(attr='float_list_indexing')
)
integer_list = fields.ListField(
StringField(attr='integer_list_indexing')
)
class Meta(object):
"""Meta options."""
model = City # The model associate with this DocType
viewsets/city.py
from django_elasticsearch_dsl_drf.constants import (
LOOKUP_FILTER_GEO_DISTANCE,
LOOKUP_FILTER_GEO_POLYGON,
LOOKUP_FILTER_GEO_BOUNDING_BOX,
SUGGESTER_COMPLETION,
)
from django_elasticsearch_dsl_drf.filter_backends import (
FilteringFilterBackend,
DefaultOrderingFilterBackend,
OrderingFilterBackend,
SearchFilterBackend,
SuggesterFilterBackend,
GeoSpatialFilteringFilterBackend,
GeoSpatialOrderingFilterBackend,
)
from django_elasticsearch_dsl_drf.pagination import LimitOffsetPagination
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from ..documents import CityDocument
from ..serializers import CityDocumentSerializer
class CityDocumentViewSet(BaseDocumentViewSet):
"""The CityDocument view."""
document = CityDocument
serializer_class = CityDocumentSerializer
lookup_field = 'id'
filter_backends = [
FilteringFilterBackend,
OrderingFilterBackend,
SearchFilterBackend,
GeoSpatialFilteringFilterBackend,
GeoSpatialOrderingFilterBackend,
DefaultOrderingFilterBackend,
SuggesterFilterBackend,
]
pagination_class = LimitOffsetPagination
# Define search fields
search_fields = (
'name',
'info',
)
search_nested_fields = {
'country': {
'path': 'country',
'fields': ['name'],
}
}
# Define filtering fields
filter_fields = {
'id': None,
'name': 'name.raw',
'country': 'country.name.raw',
}
# Define geo-spatial filtering fields
geo_spatial_filter_fields = {
'location': {
'lookups': [
LOOKUP_FILTER_GEO_BOUNDING_BOX,
LOOKUP_FILTER_GEO_DISTANCE,
LOOKUP_FILTER_GEO_POLYGON,
],
},
}
# Define ordering fields
ordering_fields = {
'id': None,
'name': None,
'country': 'country.name.raw',
}
# Define ordering fields
geo_spatial_ordering_fields = {
'location': None,
}
# Specify default ordering
ordering = (
'id',
'name.raw',
'country.name.raw',
)
# Suggester fields
suggester_fields = {
'name_suggest': {
'field': 'name.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
},
'country_suggest': {
'field': 'country.name.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
}
}
Suggestions¶
The suggest feature suggests similar looking terms based on a provided text by using a suggester.
Note
The SuggesterFilterBackend
filter backend can be used in the
suggest
custom view action/route only. Usages outside of the are
suggest
action/route are restricted.
There are three options available here: term
, phrase
and
completion
.
Note
Suggestion functionality is exclusive. Once you have queried the
SuggesterFilterBackend
, the latter will transform your current
search query into suggestion search query (which is very different).
Therefore, always add it as the very last filter backend.
Suggest completion for field country
.
http://127.0.0.1:8000/search/addresses/suggest/?country_suggest__completion=Ar
Suggest completion for field city
.
http://127.0.0.1:8000/search/addresses/suggest/?city_suggest__completion=Ye
Nested aggregations/facets¶
At the moment, nested aggregations/facets are not supported out of the box. Out of the box support will surely land in the package one day, but for now, there’s a simple and convenient way of implementing nested aggregations/facets with minimal efforts. Consider the following example.
search_indexes/backends/nested_continents.py
from django_elasticsearch_dsl_drf.filter_backends.mixins import (
FilterBackendMixin,
)
from rest_framework.filters import BaseFilterBackend
class NestedContinentsBackend(BaseFilterBackend, FilterBackendMixin):
"""Adds nesting to continents."""
faceted_search_param = 'nested_facet'
def get_faceted_search_query_params(self, request):
"""Get faceted search query params.
:param request: Django REST framework request.
:type request: rest_framework.request.Request
:return: List of search query params.
:rtype: list
"""
query_params = request.query_params.copy()
return query_params.getlist(self.faceted_search_param, [])
def filter_queryset(self, request, queryset, view):
"""Filter the queryset.
:param request: Django REST framework request.
:param queryset: Base queryset.
:param view: View.
:type request: rest_framework.request.Request
:type queryset: elasticsearch_dsl.search.Search
:type view: rest_framework.viewsets.ReadOnlyModelViewSet
:return: Updated queryset.
:rtype: elasticsearch_dsl.search.Search
"""
facets = self.get_faceted_search_query_params(request)
if 'continent' in facets:
queryset \
.aggs\
.bucket('continents',
'nested',
path='continent') \
.bucket('continent_name',
'terms',
field='continent.name.raw',
size=10) \
.bucket('counties',
'nested',
path='continent.country') \
.bucket('country_name',
'terms',
field='continent.country.name.raw',
size=10) \
.bucket('city',
'nested',
path='continent.country.city') \
.bucket('city_name',
'terms',
field='continent.country.city.name.raw',
size=10)
return queryset
The view will look as follows:
search_indexes/viewsets/address.py
from django_elasticsearch_dsl_drf.constants import (
LOOKUP_FILTER_GEO_DISTANCE,
LOOKUP_FILTER_GEO_POLYGON,
LOOKUP_FILTER_GEO_BOUNDING_BOX,
SUGGESTER_COMPLETION,
)
from django_elasticsearch_dsl_drf.filter_backends import (
DefaultOrderingFilterBackend,
FacetedSearchFilterBackend,
FilteringFilterBackend,
GeoSpatialFilteringFilterBackend,
GeoSpatialOrderingFilterBackend,
NestedFilteringFilterBackend,
OrderingFilterBackend,
SearchFilterBackend,
SuggesterFilterBackend,
)
from django_elasticsearch_dsl_drf.pagination import LimitOffsetPagination
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from ..backends import NestedContinentsBackend
from ..documents import AddressDocument
from ..serializers import AddressDocumentSerializer
class AddressDocumentViewSet(DocumentViewSet):
"""The AddressDocument view."""
document = AddressDocument
serializer_class = AddressDocumentSerializer
lookup_field = 'id'
filter_backends = [
FacetedSearchFilterBackend,
FilteringFilterBackend,
OrderingFilterBackend,
SearchFilterBackend,
GeoSpatialFilteringFilterBackend,
GeoSpatialOrderingFilterBackend,
NestedContinentsBackend,
NestedFilteringFilterBackend,
DefaultOrderingFilterBackend,
SuggesterFilterBackend,
]
pagination_class = LimitOffsetPagination
# Define search fields
search_fields = (
'street',
'zip_code',
'city.name',
'city.country.name',
)
# Define filtering fields
filter_fields = {
'id': None,
'city': 'city.name.raw',
}
# Nested filtering fields
nested_filter_fields = {
'continent_country': {
'field': 'continent.country.name.raw',
'path': 'continent.country',
},
'continent_country_city': {
'field': 'continent.country.city.name.raw',
'path': 'continent.country.city',
},
}
# Define geo-spatial filtering fields
geo_spatial_filter_fields = {
'location': {
'lookups': [
LOOKUP_FILTER_GEO_BOUNDING_BOX,
LOOKUP_FILTER_GEO_DISTANCE,
LOOKUP_FILTER_GEO_POLYGON,
],
},
}
# Define ordering fields
ordering_fields = {
'id': None,
'street': None,
'city': 'city.name.raw',
'country': 'city.country.name.raw',
'zip_code': None,
}
# Define ordering fields
geo_spatial_ordering_fields = {
'location': None,
}
# Specify default ordering
ordering = (
'id',
'street.raw',
'city.name.raw',
)
# Suggester fields
suggester_fields = {
'street_suggest': {
'field': 'street.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
},
'city_suggest': {
'field': 'city.name.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
},
'country_suggest': {
'field': 'city.country.name.suggest',
'suggesters': [
SUGGESTER_COMPLETION,
],
}
}
# Facets
faceted_search_fields = {
'city': {
'field': 'city.name.raw',
'enabled': True,
},
'country': {
'field': 'city.country.name.raw',
'enabled': True,
},
}
More like this¶
More like this functionality.
Usage example¶
Sample document¶
from django.conf import settings
from django_elasticsearch_dsl import DocType, Index, fields
from django_elasticsearch_dsl_drf.compat import KeywordField, StringField
from django_elasticsearch_dsl_drf.analyzers import edge_ngram_completion
from books.models import Book
from .analyzers import html_strip
INDEX = Index(settings.ELASTICSEARCH_INDEX_NAMES[__name__])
# See Elasticsearch Indices API reference for available settings
INDEX.settings(
number_of_shards=1,
number_of_replicas=1,
blocks={'read_only_allow_delete': False}
)
@INDEX.doc_type
class BookDocument(DocType):
# ID
id = fields.IntegerField(attr='id')
title = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'suggest': fields.CompletionField(),
'edge_ngram_completion': StringField(
analyzer=edge_ngram_completion
),
'mlt': StringField(analyzer='english'),
}
)
description = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'mlt': StringField(analyzer='english'),
}
)
summary = StringField(
analyzer=html_strip,
fields={
'raw': KeywordField(),
'mlt': StringField(analyzer='english'),
}
)
# ...
class Meta(object):
"""Meta options."""
model = Book # The model associate with this DocType
def prepare_summary(self, instance):
"""Prepare summary."""
return instance.summary[:32766]
Sample view¶
from django_elasticsearch_dsl_drf.filter_backends import (
FilteringFilterBackend,
IdsFilterBackend,
OrderingFilterBackend,
PostFilterFilteringFilterBackend,
SearchFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import (
DocumentViewSet,
MoreLikeThisMixin,
)
from .serializers import BookDocumentSerializer
class BookMoreLikeThisDocumentViewSet(DocumentViewSet,
MoreLikeThisMixin):
"""Same as BookDocumentViewSet, with more-like-this and no facets."""
# ...
document = BookDocument
lookup_field = 'id'
serializer_class = BookDocumentSerializer
# ...
filter_backends = [
# ...
FilteringFilterBackend,
PostFilterFilteringFilterBackend,
IdsFilterBackend,
OrderingFilterBackend,
SearchFilterBackend,
# ...
]
# More-like-this options
more_like_this_options = {
'fields': (
'title.mlt',
'summary.mlt',
'description.mlt',
)
}
Sample request¶
http://localhost:8000/search/books-more-like-this-no-options/1007587/more_like_this/
Generated query¶
{
"query": {
"more_like_this": {
"fields": [
"title.mlt",
"summary.mlt",
"description.mlt"
],
"like": {
"_index": "book",
"_id": "1007587",
"_type": "book_document"
}
}
},
"from": 0,
"size": 14,
"sort": [
"_score"
]
}
Options¶
Pretty much all Elasticsearch more-like-this options available. You might be particularly interested in the following:
- min_term_freq
- max_query_terms
- unlike
- stop_words
Global aggregations¶
Global aggregations (facets) are regular aggregations, which are not influenced by the search query/filter. They deliver results similar to post_filter.
Sample view¶
from django_elasticsearch_dsl_drf.filter_backends import (
CompoundSearchFilterBackend,
DefaultOrderingFilterBackend,
FacetedSearchFilterBackend,
OrderingFilterBackend,
)
from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet
from .documents import BookDocument
from .serializers import BookDocumentSerializer
class BookCompoundSearchBackendDocumentViewSet(DocumentViewSet):
document = BookDocument
serializer_class = BookDocumentSerializer
lookup_field = 'id'
filter_backends = [
# ...
OrderingFilterBackend,
DefaultOrderingFilterBackend,
CompoundSearchFilterBackend,
FacetedSearchFilterBackend,
# ...
]
faceted_search_fields = {
'state_global': {
'field': 'state.raw',
'enabled': True,
'global': True, # This makes the aggregation global
},
}
Sample request¶
http://localhost:8000/search/books/?facet=state_global&state=rejected
Generated query¶
{
"from":0,
"query":{
"bool":{
"filter":[
{
"terms":{
"state.raw":[
"rejected"
]
}
}
]
}
},
"size":25,
"aggs":{
"_filter_state_global":{
"aggs":{
"state_global":{
"terms":{
"field":"state.raw"
}
}
},
"global":{
}
}
},
"sort":[
"id",
"title",
"price"
]
}
Sample response¶
{
"count": 25,
"next": null,
"previous": null,
"facets": {
"_filter_state_global": {
"state_global": {
"buckets": [
{
"doc_count": 29,
"key": "not_published"
},
{
"doc_count": 25,
"key": "in_progress"
},
{
"doc_count": 25,
"key": "rejected"
},
{
"doc_count": 21,
"key": "cancelled"
},
{
"doc_count": 17,
"key": "published"
}
],
"sum_other_doc_count": 0,
"doc_count_error_upper_bound": 0
},
"doc_count": 117
}
},
"results": [
{
"id": 1007489,
"title": "Cupiditate qui nulla itaque maxime impedit.",
"description": null,
"summary": "Aut recusandae architecto incidunt quaerat odio .",
"authors": [
"Evy Vermeulen",
"Tycho Weijland",
"Rik Zeldenrust"
],
"publisher": "Overdijk Inc",
"publication_date": "2014-02-28",
"state": "rejected",
"isbn": "978-0-15-184366-4",
"price": 6.53,
"pages": 82,
"stock_count": 30,
"tags": [
"Trilogy"
],
"highlight": {},
"null_field": null,
"score": null
},
# ...
]
}
Configuration tweaks¶
Ignore certain Elasticsearch exceptions¶
class BookIgnoreIndexErrorsDocumentViewSet(DocumentViewSet):
# ...
ignore = [404]
# ...
Source filtering backend¶
Allows to control how the _source field is returned with every hit.
By default operations return the contents of the _source field unless you have used the stored_fields parameter or if the _source field is disabled.
You can turn off _source retrieval by using the source parameter:
from django_elasticsearch_dsl_drf.filter_backends import (
SourceBackend
)
from django_elasticsearch_dsl_drf.viewsets import (
BaseDocumentViewSet,
)
# Local article document definition
from .documents import ArticleDocument
# Local article document serializer
from .serializers import ArticleDocumentSerializer
class ArticleDocumentView(BaseDocumentViewSet):
document = ArticleDocument
serializer_class = ArticleDocumentSerializer
filter_backends = [SourceBackend,]
source = ["title"]
To disable _source retrieval set to False:
# ...
source = False
# ...
The source also accepts one or more wildcard patterns to control what parts of the _source should be returned:
# ...
source = ["title", "author.*"]
# ...
Finally, for complete control, you can specify both includes and excludes patterns:
# ...
source = {
"includes": ["title", "author.*"],
"excludes": [ "*.description" ]
}
# ...
Note
Source can make queries lighter. However, it can break current functionality. Use it with caution.
Indexing troubleshooting¶
When indexing lots of data (millions of records), you might get timeout exceptions.
A couple of possible solutions (complementary) are listed below. All of them are independent and not strictly related to each other. Thus, you may just use one or a couple or all of them. It’s totally up to you.
If you want to test what works best for you, use this test dataset (Postgres) containing 1.8 million location records for search_indexes.documents.location.LocationDocument document.
Timeout¶
For re-indexing, you might want to increase the timeout to avoid time-out exceptions.
To do that, make a new settings file (indexing) and add the following:
settings/indexing.py
from .base import * # Import from your main/production settings.
# Override the elasticsearch configuration and provide a custom timeout
ELASTICSEARCH_DSL = {
'default': {
'hosts': 'localhost:9200',
'timeout': 60, # Custom timeout
},
}
Then rebuild your search index specifying the indexing settings:
./manage.py search_index --rebuild -f --settings=settings.indexing
Note, that you may as well specify the timeout in your global settings. However, if you’re happy with how things work in production (except for the indexing part), you may do as suggested (separate indexing settings).
Chunk size¶
Note, that this feature is (yet) only available in the forked version barseghyanartur/django-elasticsearch-dsl.
Install it as follows:
pip install https://github.com/barseghyanartur/django-elasticsearch-dsl/archive/mjl-index-speedup-2-additions.zip
Specify the chunk_size param as follows (we set chunk_size to 50 in this case):
./manage.py search_index --rebuild -f --chunk-size=50
Use parallel indexing¶
Parallel indexing speeds things up (drastically). In my tests I got a speedup boost of 66 percent on 1.8 million records.
Note, that this feature is (yet) only available in the forked versions barseghyanartur/django-elasticsearch-dsl. or mjl/django-elasticsearch-dsl.
Install it as follows:
barseghyanartur/django-elasticsearch-dsl fork
pip install https://github.com/barseghyanartur/django-elasticsearch-dsl/archive/mjl-index-speedup-2-additions.zip
mjl/django-elasticsearch-dsl fork
pip install https://github.com/mjl/django-elasticsearch-dsl/archive/mjl-index-speedup.zip
In order to make use of it, define set parallel_indexing to True on the document meta.
yourapp/documents.py
class LocationDocument(DocType):
# ...
class Meta(object):
"""Meta options."""
model = Location
parallel_indexing = True
Limit the number of items indexed at once¶
This is very close to the chunk_size shown above, but might work better on heavy querysets. Instead of processing entire queryset at once, it’s sliced instead. So, if you have 2 million records in your queryset and you wish to index them by chunks of 20 thousands at once, specify the queryset_pagination on the document meta:
yourapp/documents.py
class LocationDocument(DocType):
# ...
class Meta(object):
"""Meta options."""
model = Location
queryset_pagination = 50
You may even make it dynamic based on the settings loaded. So, for instance, you may have it set to None in production (if you were happy with how things were) and provide a certain value for it in the dedicated indexing settings (as already has been mentioned above).
settings/base.py
# Main/production settings
ELASTICSEARCH_DSL_QUERYSET_PAGINATION = None
settings/indexing.py
# Indexing only settings
ELASTICSEARCH_DSL_QUERYSET_PAGINATION = 1000
yourapp/documents.py
from django.conf import settings
# ...
class LocationDocument(DocType):
# ...
class Meta(object):
"""Meta options."""
model = Location
queryset_pagination = settings.ELASTICSEARCH_DSL_QUERYSET_PAGINATION
FAQ¶
You will find a lot of useful information in the documentation.
Additionally, all raised issues that were questions have been marked as question, so you could take a look at the closed (question) issues.
Questions and answers¶
Question
- Is it possible to search sub string in word?
- How to implement partial/fuzzy search?
Answer
Yes. There are many ways doing this in Elasticsearch.
To mention a couple:
- You could use partial matching using NGrams. Partially shown here. The basic idea.
- Use contains functional filter.
Question
Can we use Django REST Framework serializers.ModelSerializer
directly?
Answer
No, but you could use serializers.Serializer
. Read the docs.
Question
How can I order search results overall relevance
Answer
That’s _score
. See the following example.
ordering = ('_score', 'id', 'title', 'price',)
In the given example, results are sorted by the score
(which is relevance),
then by id
, title
and price
.
Question
How can I separate my development/production/acceptance/test indexes?
Answer
It’s documented here.
Question
How can I sync my database with Elasticsearch indexes.
Answer
It’s documented here.
frontend demo for django-elasticsearch-dsl-drf¶
Frontend demo for django-elasticsearch-dsl-drf
Based on Book model, BookDocument and BookFrontendDocumentViewSet viewset.
Quick start¶
From the project root directory.
Install the django requirements¶
Since project supports Django versions from 1.8 to 2.1, you may install any version you want.
To install latest LTS version, do:
pip install -r examples/requirements/django_1_11.txt
Install Elasticsearch requirements¶
Since project supports Elasticsearch versions from 2.x to 6.x, you may install any version you want.
To install requirements for 6.x, do:
pip install -r examples/requirements/elastic_6x.txt
Run Elasticsearch¶
It’s really easy using Docker.
To run 6.3.2 using Docker, do:
docker pull docker.elastic.co/elasticsearch/elasticsearch:6.3.2
docker run -p 9200:9200 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:6.3.2
Build Elasticsearch index¶
First, create some test data:
./scripts/create_test_data.sh
Then build Elasticsearch index:
./scripts/rebuild_index.sh
Install React requirements¶
Note, that you should be using NodeJS > 7.5.
Typically, you would first do:
nvm use 9
Then run the installer:
./scripts/yarn_install.sh
Run Django¶
The following script would run the Django server which is used by the demo app.
./scripts/runserver.sh
Run React demo app¶
Finally, run the React demo app:
./scripts/frontend.sh
Open http://localhost:3000 to view the frontend in the browser.
Release history and notes¶
Sequence based identifiers are used for versioning (schema follows below):
major.minor[.revision]
- It’s always safe to upgrade within the same minor version (for example, from 0.3 to 0.3.4).
- Minor version changes might be backwards incompatible. Read the release notes carefully before upgrading (for example, when upgrading from 0.3.4 to 0.4).
- All backwards incompatible changes are mentioned in this document.
0.18¶
2019-06-26
Note
Support for Django versions prior 1.11 has been dropped. Support for Django REST Framework prior 3.9 has been dropped.
- Dropping support for Django versions prior 1.11.
- Dropping support for Django REST Framework versions prior 3.9.
- Fix Django REST Framework deprecations.
0.17.7¶
2019-05-30
Note
Support for Django 1.8, 1.9 and 1.10 will be dropped in the next release. As usual, compatibility shims won’t be removed directly. The change will affect the test matrix only first.
- Prevent unicode errors in tests on Python 2.7.
- Fixes in occasionally failing search test (
test_search
andtest_filtering_geo_spatial
). - Working travis.
- Fixed issue with errors on empty
ids
filter.
0.17.5¶
2019-04-03
Note
Dropping support for Python 3.4. As of this version everything works, but no longer tested.
- Minor fixes.
- Dropping Python 3.4 support.
- Django 2.2 support.
0.17.1¶
2018-12-12
- Skipping the new context suggester tests for Elasticsearch 2.x and a number of other 2.x related fixes in tests.
- A number of 5.x fixes in tests.
0.17¶
2018-12-12
Note
Release supported by whythawk.
- Added support for context suggesters (category and geo). Note, that this functionality is available for Elasticsearch 5.x and 6.x (thus, not for Elasticsearch 2.x).
- Added support for size attribute on suggesters.
0.16.3¶
2018-10-31
Note
Release dedicated to Charles Aznavour.
- Make it possible to ignore certain Elastic exceptions by providing the
appropriate
ignore
argument (on the view level). Default behaviour is intact. Set it to a list of integers (error codes) if you need it so.
0.16¶
2018-09-10
Note
This release contains minor backwards incompatible changes. You might need to update your code if you have been making use of nested search.
Old way of declaring nested search fields
search_nested_fields = {
'country': ['name'],
'country.city': ['name'],
}
New way of declaring nested search fields
search_nested_fields = {
'country': {
'path': 'country',
'fields': ['name'],
},
'city': {
'path': 'country.city',
'fields': ['name'],
},
}
- Changes in nested search. This affects usage of both historical
SearchFilterBackend
andCompoundSearchFilterBackend
. Update your code accordingly. - Take meta property
using
of the documentMeta
into consideration.
0.13.2¶
2018-08-03
- Successfully tested against Python 3.7 and Django 2.1.
- Unified the base
BaseSearchFilterBackend
class. - Minor clean up and fixes in docs.
- Upgrading test suite to modern versions (
pytest
,tox
,factory_boy
,Faker
). Removing unused dependencies from requirements (drf-extensions
). - Fixed missing PDF generation in offline documentation (non ReadTheDocs).
The
rst2pdf
package (which does not support Python 3) has been replaced withrinohtype
package (which does support Python 3).
0.13¶
2018-07-23
Note
Release dedicated to Guido van Rossum, the former Python BDFL, who resigned from his BDFL position recently. Guido knew it better than we all do. His charisma, talent and leadership will be certainly missed a lot by the community. Thumbs up again for the best BDFL ever.
- The
SimpleQueryStringSearchFilterBackend
backend has been implemented. - Minor fixes in the
MultiMatchSearchFilterBackend
backend.
0.12¶
2018-07-21
- New-style Search Filter Backends. Old style
SearchFilterBackend
is still supported (until at least version 0.16), but is deprecated. Migrate toCompoundSearchFilterBackend
.MultiMatchSearchFilterBackend
introduced (the name speaks for itself). - From now on, your views would also work with model- and object-level
permissions of the Django REST Framework (such as
DjangoModelPermissions
,DjangoModelPermissionsOrAnonReadOnly
andDjangoObjectPermissions
). Correspondent model or object would be used for that. If you find it incorrect in your case, write custom permissions and declare the explicitly in your view-sets. - Fixed geo-spatial
geo_distance
ordering for Elastic 5.x. and 6.x. - Fixes occasionally failing tests.
0.11¶
2018-07-15
Note
This release contains backwards incompatible changes.
You should update your Django code and front-end parts of your applications
that were relying on the complex queries using |
and :
chars in the
GET params.
Note
If you have used custom filter backends using SEPARATOR_LOOKUP_VALUE
,
SEPARATOR_LOOKUP_COMPLEX_VALUE
or
SEPARATOR_LOOKUP_COMPLEX_MULTIPLE_VALUE
constants or
split_lookup_complex_value
helper method of the FilterBackendMixin
,
you most likely want to run your functional tests to see if everything
still works.
Note
Do not keep things as they were in your own fork, since new search backends
will use the |
and :
symbols differently.
Examples of old API requests vs new API requests
Note
Note, that |
and :
chars were mostly replaced with __
and ,
.
Old API requests
http://127.0.0.1:8080/search/publisher/?search=name|reilly&search=city|london
http://127.0.0.1:8000/search/publishers/?location__geo_distance=100000km|12.04|-63.93
http://localhost:8000/api/articles/?id__terms=1|2|3
http://localhost:8000/api/users/?age__range=16|67|2.0
http://localhost:8000/api/articles/?id__in=1|2|3
http://localhost:8000/api/articles/?location__geo_polygon=40,-70|30,-80|20,-90|_name:myname|validation_method:IGNORE_MALFORMED
New API requests
http://127.0.0.1:8080/search/publisher/?search=name:reilly&search=city:london
http://127.0.0.1:8000/search/publishers/?location__geo_distance=100000km__12.04__-63.93
http://localhost:8000/api/articles/?id__terms=1__2__3
http://localhost:8000/api/users/?age__range=16__67__2.0
http://localhost:8000/api/articles/?id__in=1__2__3
http://localhost:8000/api/articles/?location__geo_polygon=40,-70__30,-80__20,-90___name,myname__validation_method,IGNORE_MALFORMED
SEPARATOR_LOOKUP_VALUE
has been removed. UseSEPARATOR_LOOKUP_COMPLEX_VALUE
andSEPARATOR_LOOKUP_COMPLEX_MULTIPLE_VALUE
instead.SEPARATOR_LOOKUP_NAME
has been added.- The method
split_lookup_complex_value
has been removed. Usesplit_lookup_complex_value
instead. - Default filter lookup option is added. In past, if no specific lookup was
provided and there were multiple values for a single field to filter on, by
default
terms
filter was used. Theterm
lookup was used by default in similar situation for a single value to filter on. It’s now possible to declare default lookup which will be used when no lookup is given. - Removed deprecated
views
module. Import fromviewsets
instead. - Removed undocumented
get_count
helper fromhelpers
module.
0.9¶
2018-07-04
- Introduced
post_filter
support. - Generalised the
FilteringFilterBackend
backend. BothPostFilterFilteringFilterBackend
andNestedFilteringFilterBackend
backends are now primarily based on it. - Reduced Elastic queries from 3 to 2 when using
LimitOffsetPagination
.
0.8.4¶
2018-06-27
Note
Release supported by Goldmund, Wyldebeast & Wunderliebe.
- Added
NestedFilteringFilterBackend
backend. - Documentation updated with examples of implementing a nested aggregations/facets.
0.8.3¶
2018-06-25
- It’s possible to retrieve original dictionary from
DictionaryProxy
object. - Added helper wrappers and helper functions as a temporary fix for issues
in the
django-elasticsearch-dsl
.
0.8.1¶
2018-06-05
- Fixed wrong filter name in functional suggesters results into an error on Django 1.10 (and prior).
- Documentation improvements.
0.8¶
2018-06-01
Note
Release supported by Goldmund, Wyldebeast & Wunderliebe.
Note
This release contain minor backwards incompatible changes. You should update your code.
BaseDocumentViewSet
(which from now on does not containsuggest
functionality) has been renamed toDocumentViewSet
(which does containsuggest
functionality).
- You should no longer import from
django_elasticsearch_dsl_drf.views
. Instead, import fromdjango_elasticsearch_dsl_drf.viewsets
.
- You should no longer import from
- Deprecated
django_elasticsearch_dsl_drf.views
in favour ofdjango_elasticsearch_dsl_drf.viewsets
. - Suggest action/method has been moved to
SuggestMixin
class. FunctionalSuggestMixin
class introduced which resembled functionality of theSuggestMixin
with several improvements/additions, such as advanced filtering and context-aware suggestions.- You can now define a default suggester in
suggester_fields
which will be used if you do not provide suffix for the filter name.
0.7.2¶
2018-05-09
Note
Release dedicated to the Victory Day, the victims of the Second World War and Liberation of Shushi.
- Django REST framework 3.8.x support.
0.7.1¶
2018-04-04
Note
Release supported by Goldmund, Wyldebeast & Wunderliebe.
- Add query boost support for search fields.
0.7¶
2018-03-08
Note
Dear ladies, congratulations on International Women’s Day
- CoreAPI/CoreSchema support.
0.6.2¶
2017-12-29
- Update example project (and the tests that are dependant on the example project) to work with Django 2.0.
- Set minimal requirement for
django-elasticsearch-dsl
to 3.0.
0.5.1¶
2017-10-18
- Fixed serialization of complex nested structures (lists of nested objects).
- Documentation fixes.
0.5¶
2017-10-05
Note
This release contains changes that might be backwards incompatible
for your project. If you have used dynamic document serializer
django_elasticsearch_dsl_drf.serializers.DocumentSerializer
with customisations (with use of serializers.SerializerMethodField
,
having the value parsed to JSON), just remove the custom parts.
- Support for
ObjectField
,NestedField
,GeoPointField
,ListField
,GeoShapeField
(and in general, nesting fields either as a dictionary or list should not be a problem at all). - Dynamic serializer has been made less strict.
- Added
get_paginated_response_context
methods to bothPageNumberPagination
andLimitOffsetPagination
pagination classes to simplify customisations.
0.4.4¶
2017-10-02
- Documentation improvements (Elasticsearch suggestions).
- More tests (term and phrase suggestions).
- Code style fixes.
0.4¶
2017-09-26
Note
This release contains changes that might be backwards incompatible
for your project. Make sure to add the DefaultOrderingFilterBackend
everywhere you have used the OrderingFilterBackend
, right after the
latter.
GeoSpatialFilteringFilterBackend
filtering backend, supportinggeo_distance
andgeo_polygon
geo-spatial queries.GeoSpatialOrderingFilterBackend
ordering backend, supporting ordering of results forgeo_distance
filter.OrderingFilterBackend
no longer provides defaults when no ordering is given. In order to take care of the defaults include theDefaultOrderingFilterBackend
in the list offilter_backends
(after all other ordering backends).
0.3.12¶
2017-09-21
- Added
geo_distance
filter. Note, that although functionally the filter would not change its’ behaviour, it is likely to be moved to a separate backend (geo_spatial
). For now use as is. - Minor fixes.
0.3.6¶
2017-09-07
- Fixed suggestions test for Elasticsearch 5.x.
- Added compat module for painless testing of Elastic 2.x to Elastic 5.x transition.
0.1.6¶
2017-06-23
- Implemented
gt
,gte
,lt
andlte
functional query lookups. - Implemented
ids
native filter lookup.
0.1.5¶
2017-06-22
- Implemented
endswith
andcontains
functional filters. - Added tests for
wildcard
,exists
,exclude
andisnull
filters. Improvedrange
filter tests. - Improve
more_like_this
helper test. - Improve ordering tests.
- Two additional arguments added to the
more_like_this
helper:min_doc_freq
andmax_doc_freq
. - Minor documentation improvements.
0.1.3¶
2017-06-21
- Added tests for
more_like_this
helper,range
andprefix
filters. - Minor documentation improvements.
django_elasticsearch_dsl_drf package¶
Subpackages¶
django_elasticsearch_dsl_drf.fields package¶
Submodules¶
django_elasticsearch_dsl_drf.fields.common module¶
Common fields.
-
class
django_elasticsearch_dsl_drf.fields.common.
BooleanField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
rest_framework.fields.BooleanField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.common.
CharField
(**kwargs)[source]¶ Bases:
rest_framework.fields.CharField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.common.
DateField
(format=<class 'rest_framework.fields.empty'>, input_formats=None, *args, **kwargs)[source]¶ Bases:
rest_framework.fields.DateField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.common.
FloatField
(**kwargs)[source]¶ Bases:
rest_framework.fields.FloatField
Object field.
django_elasticsearch_dsl_drf.fields.helpers module¶
Helpers.
django_elasticsearch_dsl_drf.fields.nested_fields module¶
Nested fields.
-
class
django_elasticsearch_dsl_drf.fields.nested_fields.
GeoPointField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
django_elasticsearch_dsl_drf.fields.nested_fields.ObjectField
Geo point field.
-
class
django_elasticsearch_dsl_drf.fields.nested_fields.
GeoShapeField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
django_elasticsearch_dsl_drf.fields.nested_fields.ObjectField
Geo shape field.
-
class
django_elasticsearch_dsl_drf.fields.nested_fields.
NestedField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
django_elasticsearch_dsl_drf.fields.nested_fields.ObjectField
Nested field.
-
class
django_elasticsearch_dsl_drf.fields.nested_fields.
ObjectField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
rest_framework.fields.Field
Object field.
-
class
django_elasticsearch_dsl_drf.fields.nested_fields.
ListField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
rest_framework.fields.Field
List field.
Module contents¶
Fields.
-
class
django_elasticsearch_dsl_drf.fields.
BooleanField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
rest_framework.fields.BooleanField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.
CharField
(**kwargs)[source]¶ Bases:
rest_framework.fields.CharField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.
DateField
(format=<class 'rest_framework.fields.empty'>, input_formats=None, *args, **kwargs)[source]¶ Bases:
rest_framework.fields.DateField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.
FloatField
(**kwargs)[source]¶ Bases:
rest_framework.fields.FloatField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.
GeoPointField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
django_elasticsearch_dsl_drf.fields.nested_fields.ObjectField
Geo point field.
-
class
django_elasticsearch_dsl_drf.fields.
GeoShapeField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
django_elasticsearch_dsl_drf.fields.nested_fields.ObjectField
Geo shape field.
-
class
django_elasticsearch_dsl_drf.fields.
IntegerField
(**kwargs)[source]¶ Bases:
rest_framework.fields.IntegerField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.
IPAddressField
(protocol='both', **kwargs)[source]¶ Bases:
rest_framework.fields.IPAddressField
Object field.
-
class
django_elasticsearch_dsl_drf.fields.
ListField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
rest_framework.fields.Field
List field.
-
class
django_elasticsearch_dsl_drf.fields.
NestedField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
django_elasticsearch_dsl_drf.fields.nested_fields.ObjectField
Nested field.
-
class
django_elasticsearch_dsl_drf.fields.
ObjectField
(read_only=False, write_only=False, required=None, default=<class 'rest_framework.fields.empty'>, initial=<class 'rest_framework.fields.empty'>, source=None, label=None, help_text=None, style=None, error_messages=None, validators=None, allow_null=False)[source]¶ Bases:
rest_framework.fields.Field
Object field.
django_elasticsearch_dsl_drf.filter_backends package¶
Subpackages¶
Common filtering backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.common.
FilteringFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Filtering filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> FilteringFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [FilteringFilterBackend,] >>> filter_fields = { >>> 'title': 'title.raw', >>> 'state': { >>> 'field': 'state.raw', >>> 'lookups': [ >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ], >>> 'default_lookup': LOOKUP_FILTER_WILDCARD, >>> } >>> }
-
classmethod
apply_filter_prefix
(queryset, options, value)[source]¶ Apply prefix filter.
Syntax:
/endpoint/?field_name__prefix={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_filter_range
(queryset, options, value)[source]¶ Apply range filter.
Syntax:
/endpoint/?field_name__range={lower}__{upper}__{boost} /endpoint/?field_name__range={lower}__{upper}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_filter_term
(queryset, options, value)[source]¶ Apply term filter.
Syntax:
/endpoint/?field_name={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_filter_terms
(queryset, options, value)[source]¶ Apply terms filter.
Syntax:
/endpoint/?field_name__terms={value1}__{value2} /endpoint/?field_name__terms={value1}Note, that number of values is not limited.
Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (mixed: either str or iterable (list, tuple)) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_contains
(queryset, options, value)[source]¶ Apply contains filter.
Syntax:
/endpoint/?field_name__contains={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_endswith
(queryset, options, value)[source]¶ Apply endswith filter.
Syntax:
/endpoint/?field_name__endswith={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_exclude
(queryset, options, value)[source]¶ Apply exclude functional query.
Syntax:
/endpoint/?field_name__isnull={value1}__{value2} /endpoint/?field_name__exclude={valu1}Note, that number of values is not limited.
Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_exists
(queryset, options, value)[source]¶ Apply exists filter.
Syntax:
/endpoint/?field_name__exists=true /endpoint/?field_name__exists=falseExample:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_gt
(queryset, options, value)[source]¶ Apply gt functional query.
Syntax:
/endpoint/?field_name__gt={value}__{boost} /endpoint/?field_name__gt={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_gte
(queryset, options, value)[source]¶ Apply gte functional query.
Syntax:
/endpoint/?field_name__gte={value}__{boost} /endpoint/?field_name__gte={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_in
(queryset, options, value)[source]¶ Apply in functional query.
Syntax:
/endpoint/?field_name__in={value1}__{value2} /endpoint/?field_name__in={value1}Note, that number of values is not limited.
Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_isnull
(queryset, options, value)[source]¶ Apply isnull functional query.
Syntax:
/endpoint/?field_name__isnull=true /endpoint/?field_name__isnull=falseExample:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_lt
(queryset, options, value)[source]¶ Apply lt functional query.
Syntax:
/endpoint/?field_name__lt={value}__{boost} /endpoint/?field_name__lt={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_lte
(queryset, options, value)[source]¶ Apply lte functional query.
Syntax:
/endpoint/?field_name__lte={value}__{boost} /endpoint/?field_name__lte={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_wildcard
(queryset, options, value)[source]¶ Apply wildcard filter.
Syntax:
/endpoint/?field_name__wildcard={value}* /endpoint/?field_name__wildcard=*{value} /endpoint/?field_name__wildcard=*{value}*Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_filter_query_params
(request, view)[source]¶ Get query params to be filtered on.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Request query params to filter on.
Return type: dict
-
classmethod
get_gte_lte_params
(value, lookup)[source]¶ Get params for gte, gt, lte and lt query.
Syntax:
/endpoint/?field_name__gt={lower}__{boost} /endpoint/?field_name__gt={lower}Example:
Parameters: - value (str) –
- lookup (str) –
Returns: Params to be used in range query.
Return type: dict
-
classmethod
Geo spatial filtering backend.
Elasticsearch supports two types of geo data:
- geo_point fields which support lat/lon pairs
- geo_shape fields, which support points, lines, circles, polygons, multi-polygons etc.
The queries in this group are:
- geo_shape query: Find document with geo-shapes which either intersect, are contained by, or do not intersect with the specified geo-shape.
- geo_bounding_box query: Finds documents with geo-points that fall into the specified rectangle.
- geo_distance query: Finds document with geo-points within the specified distance of a central point.
- geo_distance_range query: Like the geo_distance query, but the range starts at a specified distance from the central point. Note, that this one is deprecated and this isn’t implemented.
- geo_polygon query: Find documents with geo-points within the specified polygon.
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.geo_spatial.
GeoSpatialFilteringFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Geo-spatial filtering filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> LOOKUP_FILTER_GEO_DISTANCE, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> GeoSpatialFilteringFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [GeoSpatialFilteringFilterBackend,] >>> geo_spatial_filter_fields = { >>> 'loc': 'location', >>> 'location': { >>> 'field': 'location', >>> 'lookups': [ >>> LOOKUP_FILTER_GEO_DISTANCE, >>> ], >>> } >>> }
-
classmethod
apply_query_geo_bounding_box
(queryset, options, value)[source]¶ Apply geo_bounding_box query.
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_geo_distance
(queryset, options, value)[source]¶ Apply geo_distance query.
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_geo_polygon
(queryset, options, value)[source]¶ Apply geo_polygon query.
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_filter_query_params
(request, view)[source]¶ Get query params to be filtered on.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Request query params to filter on.
Return type: dict
-
classmethod
get_geo_bounding_box_params
(value, field)[source]¶ Get params for geo_bounding_box query.
Example:
/api/articles/?location__geo_bounding_box=40.73,-74.1__40.01,-71.12Example:
- /api/articles/?location__geo_polygon=40.73,-74.1
- __40.01,-71.12 ___name,myname __validation_method,IGNORE_MALFORMED __type,indexed
Elasticsearch:
- {
- “query”: {
- “bool” : {
- “must” : {
- “match_all” : {}
}, “filter” : {
- “geo_bounding_box” : {
- “person.location” : {
- “top_left” : {
- “lat” : 40.73, “lon” : -74.1
}, “bottom_right” : {
“lat” : 40.01, “lon” : -71.12}
}
}
}
}
}
}
Parameters: - value (str) –
- field –
Returns: Params to be used in geo_bounding_box query.
Return type: dict
-
classmethod
get_geo_distance_params
(value, field)[source]¶ Get params for geo_distance query.
Example:
/api/articles/?location__geo_distance=2km__43.53__-12.23Parameters: - value (str) –
- field –
Returns: Params to be used in geo_distance query.
Return type: dict
-
classmethod
get_geo_polygon_params
(value, field)[source]¶ Get params for geo_polygon query.
Example:
/api/articles/?location__geo_polygon=40,-70__30,-80__20,-90Example:
- /api/articles/?location__geo_polygon=40,-70
- __30,-80 __20,-90 ___name,myname __validation_method,IGNORE_MALFORMED
Elasticsearch:
- {
- “query”: {
- “bool” : {
- “must” : {
- “match_all” : {}
}, “filter” : {
- “geo_polygon” : {
- “person.location” : {
- “points” : [
- {“lat” : 40, “lon” : -70}, {“lat” : 30, “lon” : -80}, {“lat” : 20, “lon” : -90}
]
}
}
}
}
}
}
Parameters: - value (str) –
- field –
Returns: Params to be used in geo_distance query.
Return type: dict
-
classmethod
Ids filtering backend.
Filters documents that only have the provided ids. Note, this query uses the _uid field.
Elastic query:
- {
- “query”: {
- “ids”: {
- “type”: “book_document”, “values”: [“68”, “64”, “58”]
}
}
}
REST framework request equivalent:
- http://localhost:8000/api/articles/?ids=68__64__58
- http://localhost:8000/api/articles/?ids=68&ids=64&ids=58
Official Elastic docs:
- https://www.elastic.co/guide/en/elasticsearch/reference/current/ query-dsl-ids-query.html
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.ids.
IdsFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Ids filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> IdsFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [IdsFilterBackend]
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_ids_query_params
(request)[source]¶ Get search query params.
Parameters: request (rest_framework.request.Request) – Django REST framework request. Returns: List of search query params. Return type: list
-
get_ids_values
(request, view)[source]¶ Get ids values for query.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
ids_query_param
= 'ids'¶
-
Nested filtering backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.nested.
NestedFilteringFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.filtering.common.FilteringFilterBackend
Nested filter backend.
Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> LOOKUP_FILTER_TERM, >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> NestedFilteringFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [NestedFilteringFilterBackend,] >>> nested_filter_fields = { >>> 'country': { >>> 'field': 'continent.country.name.raw', >>> 'path': 'continent.country', >>> 'lookups': [ >>> LOOKUP_FILTER_TERM, >>> LOOKUP_FILTER_TERMS, >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ], >>> } >>> }
-
classmethod
apply_filter
(queryset, options=None, args=None, kwargs=None)[source]¶ Apply filter.
Parameters: - queryset –
- options –
- args –
- kwargs –
Returns:
-
classmethod
apply_query
(queryset, options=None, args=None, kwargs=None)[source]¶ Apply query.
Parameters: - queryset –
- options –
- args –
- kwargs –
Returns:
-
get_filter_field_nested_path
(filter_fields, field_name)[source]¶ Get filter field path to be used in nested query.
Parameters: - filter_fields –
- field_name –
Returns:
-
classmethod
The post_filter
filtering backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.post_filter.
PostFilterFilteringFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.filtering.common.FilteringFilterBackend
The
post_filter
filtering filter backend for Elasticsearch.Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> PostFilterFilteringFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [PostFilterFilteringFilterBackend,] >>> post_filter_fields = { >>> 'title': 'title.raw', >>> 'state': { >>> 'field': 'state.raw', >>> 'lookups': [ >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ], >>> } >>> }
-
classmethod
apply_filter
(queryset, options=None, args=None, kwargs=None)[source]¶ Apply filter.
Parameters: - queryset –
- options –
- args –
- kwargs –
Returns:
-
classmethod
Term level filtering and post_filter
backends.
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.
FilteringFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Filtering filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> FilteringFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [FilteringFilterBackend,] >>> filter_fields = { >>> 'title': 'title.raw', >>> 'state': { >>> 'field': 'state.raw', >>> 'lookups': [ >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ], >>> 'default_lookup': LOOKUP_FILTER_WILDCARD, >>> } >>> }
-
classmethod
apply_filter_prefix
(queryset, options, value)[source]¶ Apply prefix filter.
Syntax:
/endpoint/?field_name__prefix={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_filter_range
(queryset, options, value)[source]¶ Apply range filter.
Syntax:
/endpoint/?field_name__range={lower}__{upper}__{boost} /endpoint/?field_name__range={lower}__{upper}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_filter_term
(queryset, options, value)[source]¶ Apply term filter.
Syntax:
/endpoint/?field_name={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_filter_terms
(queryset, options, value)[source]¶ Apply terms filter.
Syntax:
/endpoint/?field_name__terms={value1}__{value2} /endpoint/?field_name__terms={value1}Note, that number of values is not limited.
Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (mixed: either str or iterable (list, tuple)) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_contains
(queryset, options, value)[source]¶ Apply contains filter.
Syntax:
/endpoint/?field_name__contains={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_endswith
(queryset, options, value)[source]¶ Apply endswith filter.
Syntax:
/endpoint/?field_name__endswith={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_exclude
(queryset, options, value)[source]¶ Apply exclude functional query.
Syntax:
/endpoint/?field_name__isnull={value1}__{value2} /endpoint/?field_name__exclude={valu1}Note, that number of values is not limited.
Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_exists
(queryset, options, value)[source]¶ Apply exists filter.
Syntax:
/endpoint/?field_name__exists=true /endpoint/?field_name__exists=falseExample:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_gt
(queryset, options, value)[source]¶ Apply gt functional query.
Syntax:
/endpoint/?field_name__gt={value}__{boost} /endpoint/?field_name__gt={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_gte
(queryset, options, value)[source]¶ Apply gte functional query.
Syntax:
/endpoint/?field_name__gte={value}__{boost} /endpoint/?field_name__gte={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_in
(queryset, options, value)[source]¶ Apply in functional query.
Syntax:
/endpoint/?field_name__in={value1}__{value2} /endpoint/?field_name__in={value1}Note, that number of values is not limited.
Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_isnull
(queryset, options, value)[source]¶ Apply isnull functional query.
Syntax:
/endpoint/?field_name__isnull=true /endpoint/?field_name__isnull=falseExample:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_lt
(queryset, options, value)[source]¶ Apply lt functional query.
Syntax:
/endpoint/?field_name__lt={value}__{boost} /endpoint/?field_name__lt={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_lte
(queryset, options, value)[source]¶ Apply lte functional query.
Syntax:
/endpoint/?field_name__lte={value}__{boost} /endpoint/?field_name__lte={value}Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_wildcard
(queryset, options, value)[source]¶ Apply wildcard filter.
Syntax:
/endpoint/?field_name__wildcard={value}* /endpoint/?field_name__wildcard=*{value} /endpoint/?field_name__wildcard=*{value}*Example:
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_filter_query_params
(request, view)[source]¶ Get query params to be filtered on.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Request query params to filter on.
Return type: dict
-
classmethod
get_gte_lte_params
(value, lookup)[source]¶ Get params for gte, gt, lte and lt query.
Syntax:
/endpoint/?field_name__gt={lower}__{boost} /endpoint/?field_name__gt={lower}Example:
Parameters: - value (str) –
- lookup (str) –
Returns: Params to be used in range query.
Return type: dict
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.
GeoSpatialFilteringFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Geo-spatial filtering filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> LOOKUP_FILTER_GEO_DISTANCE, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> GeoSpatialFilteringFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [GeoSpatialFilteringFilterBackend,] >>> geo_spatial_filter_fields = { >>> 'loc': 'location', >>> 'location': { >>> 'field': 'location', >>> 'lookups': [ >>> LOOKUP_FILTER_GEO_DISTANCE, >>> ], >>> } >>> }
-
classmethod
apply_query_geo_bounding_box
(queryset, options, value)[source]¶ Apply geo_bounding_box query.
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_geo_distance
(queryset, options, value)[source]¶ Apply geo_distance query.
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_query_geo_polygon
(queryset, options, value)[source]¶ Apply geo_polygon query.
Parameters: - queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_filter_query_params
(request, view)[source]¶ Get query params to be filtered on.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Request query params to filter on.
Return type: dict
-
classmethod
get_geo_bounding_box_params
(value, field)[source]¶ Get params for geo_bounding_box query.
Example:
/api/articles/?location__geo_bounding_box=40.73,-74.1__40.01,-71.12Example:
- /api/articles/?location__geo_polygon=40.73,-74.1
- __40.01,-71.12 ___name,myname __validation_method,IGNORE_MALFORMED __type,indexed
Elasticsearch:
- {
- “query”: {
- “bool” : {
- “must” : {
- “match_all” : {}
}, “filter” : {
- “geo_bounding_box” : {
- “person.location” : {
- “top_left” : {
- “lat” : 40.73, “lon” : -74.1
}, “bottom_right” : {
“lat” : 40.01, “lon” : -71.12}
}
}
}
}
}
}
Parameters: - value (str) –
- field –
Returns: Params to be used in geo_bounding_box query.
Return type: dict
-
classmethod
get_geo_distance_params
(value, field)[source]¶ Get params for geo_distance query.
Example:
/api/articles/?location__geo_distance=2km__43.53__-12.23Parameters: - value (str) –
- field –
Returns: Params to be used in geo_distance query.
Return type: dict
-
classmethod
get_geo_polygon_params
(value, field)[source]¶ Get params for geo_polygon query.
Example:
/api/articles/?location__geo_polygon=40,-70__30,-80__20,-90Example:
- /api/articles/?location__geo_polygon=40,-70
- __30,-80 __20,-90 ___name,myname __validation_method,IGNORE_MALFORMED
Elasticsearch:
- {
- “query”: {
- “bool” : {
- “must” : {
- “match_all” : {}
}, “filter” : {
- “geo_polygon” : {
- “person.location” : {
- “points” : [
- {“lat” : 40, “lon” : -70}, {“lat” : 30, “lon” : -80}, {“lat” : 20, “lon” : -90}
]
}
}
}
}
}
}
Parameters: - value (str) –
- field –
Returns: Params to be used in geo_distance query.
Return type: dict
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.
IdsFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Ids filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> IdsFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [IdsFilterBackend]
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_ids_query_params
(request)[source]¶ Get search query params.
Parameters: request (rest_framework.request.Request) – Django REST framework request. Returns: List of search query params. Return type: list
-
get_ids_values
(request, view)[source]¶ Get ids values for query.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
ids_query_param
= 'ids'¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.
NestedFilteringFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.filtering.common.FilteringFilterBackend
Nested filter backend.
Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> LOOKUP_FILTER_TERM, >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> NestedFilteringFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [NestedFilteringFilterBackend,] >>> nested_filter_fields = { >>> 'country': { >>> 'field': 'continent.country.name.raw', >>> 'path': 'continent.country', >>> 'lookups': [ >>> LOOKUP_FILTER_TERM, >>> LOOKUP_FILTER_TERMS, >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ], >>> } >>> }
-
classmethod
apply_filter
(queryset, options=None, args=None, kwargs=None)[source]¶ Apply filter.
Parameters: - queryset –
- options –
- args –
- kwargs –
Returns:
-
classmethod
apply_query
(queryset, options=None, args=None, kwargs=None)[source]¶ Apply query.
Parameters: - queryset –
- options –
- args –
- kwargs –
Returns:
-
get_filter_field_nested_path
(filter_fields, field_name)[source]¶ Get filter field path to be used in nested query.
Parameters: - filter_fields –
- field_name –
Returns:
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.filtering.
PostFilterFilteringFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.filtering.common.FilteringFilterBackend
The
post_filter
filtering filter backend for Elasticsearch.Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> PostFilterFilteringFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [PostFilterFilteringFilterBackend,] >>> post_filter_fields = { >>> 'title': 'title.raw', >>> 'state': { >>> 'field': 'state.raw', >>> 'lookups': [ >>> LOOKUP_FILTER_PREFIX, >>> LOOKUP_FILTER_WILDCARD, >>> LOOKUP_QUERY_EXCLUDE, >>> LOOKUP_QUERY_ISNULL, >>> ], >>> } >>> }
-
classmethod
apply_filter
(queryset, options=None, args=None, kwargs=None)[source]¶ Apply filter.
Parameters: - queryset –
- options –
- args –
- kwargs –
Returns:
-
classmethod
Ordering backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.ordering.common.
DefaultOrderingFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.ordering.common.OrderingMixin
Default ordering filter backend for Elasticsearch.
Make sure this is your last ordering backend.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> DefaultOrderingFilterBackend, >>> OrderingFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [ >>> DefaultOrderingFilterBackend, >>> OrderingFilterBackend, >>> ] >>> ordering_fields = { >>> 'id': None, >>> 'title': 'title.raw', >>> 'date_submitted': 'date_submitted', >>> 'continent': { >>> 'field': 'continent.name.raw', >>> 'path': 'continent', >>> } >>> 'country': { >>> 'field': 'continent.country.name.raw', >>> 'path': 'continent.country', >>> } >>> 'city': { >>> 'field': 'continent.country.city.name.raw', >>> 'path': 'continent.country.city', >>> } >>> } >>> ordering = 'city'
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
get_default_ordering_params
(view)[source]¶ Get the default ordering params for the view.
Parameters: view (rest_framework.viewsets.ReadOnlyModelViewSet) – View. Returns: Ordering params to be used for ordering. Return type: list
-
get_ordering_query_params
(request, view)[source]¶ Get ordering query params.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Ordering params to be used for ordering.
Return type: list
-
ordering_param
= 'ordering'¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.ordering.common.
OrderingFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.ordering.common.OrderingMixin
Ordering filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> OrderingFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [OrderingFilterBackend,] >>> ordering_fields = { >>> 'id': None, >>> 'title': 'title.raw', >>> 'date_submitted': 'date_submitted', >>> 'continent': { >>> 'field': 'continent.name.raw', >>> 'path': 'continent', >>> } >>> 'country': { >>> 'field': 'continent.country.name.raw', >>> 'path': 'continent.country', >>> } >>> 'city': { >>> 'field': 'continent.country.city.name.raw', >>> 'path': 'continent.country.city', >>> } >>> } >>> ordering = ('id', 'title',)
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_ordering_query_params
(request, view)[source]¶ Get ordering query params.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Ordering params to be used for ordering.
Return type: list
-
ordering_param
= 'ordering'¶
-
Geo-spatial ordering backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.ordering.geo_spatial.
GeoSpatialOrderingFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Geo-spatial ordering filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> GeoSpatialOrderingFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [GeoSpatialOrderingFilterBackend,] >>> geo_spatial_ordering_fields = { >>> 'location': { >>> 'field': 'location', >>> } >>> }
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
get_geo_distance_params
(value, field)[source]¶ Get params for geo_distance ordering.
Example:
/api/articles/?ordering=-location__45.3214__-34.3421__km__planesParameters: - value (str) –
- field –
Returns: Params to be used in geo_distance query.
Return type: dict
-
get_geo_spatial_field_name
(request, view, name)[source]¶ Get geo-spatial field name.
We have to deal with a couple of situations here:
Example 1:
>>> geo_spatial_ordering_fields = { >>> 'location': None, >>> }
Example 2:
>>> geo_spatial_ordering_fields = { >>> 'location': 'location', >>> }
Example 3:
>>> geo_spatial_ordering_fields = { >>> 'location': { >>> 'field': 'location' >>> }, >>> }
Parameters: - request –
- view –
- name –
Returns:
-
get_ordering_query_params
(request, view)[source]¶ Get ordering query params.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Ordering params to be used for ordering.
Return type: list
-
ordering_param
= 'ordering'¶
-
Ordering backends.
-
class
django_elasticsearch_dsl_drf.filter_backends.ordering.
DefaultOrderingFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.ordering.common.OrderingMixin
Default ordering filter backend for Elasticsearch.
Make sure this is your last ordering backend.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> DefaultOrderingFilterBackend, >>> OrderingFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [ >>> DefaultOrderingFilterBackend, >>> OrderingFilterBackend, >>> ] >>> ordering_fields = { >>> 'id': None, >>> 'title': 'title.raw', >>> 'date_submitted': 'date_submitted', >>> 'continent': { >>> 'field': 'continent.name.raw', >>> 'path': 'continent', >>> } >>> 'country': { >>> 'field': 'continent.country.name.raw', >>> 'path': 'continent.country', >>> } >>> 'city': { >>> 'field': 'continent.country.city.name.raw', >>> 'path': 'continent.country.city', >>> } >>> } >>> ordering = 'city'
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
get_default_ordering_params
(view)[source]¶ Get the default ordering params for the view.
Parameters: view (rest_framework.viewsets.ReadOnlyModelViewSet) – View. Returns: Ordering params to be used for ordering. Return type: list
-
get_ordering_query_params
(request, view)[source]¶ Get ordering query params.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Ordering params to be used for ordering.
Return type: list
-
ordering_param
= 'ordering'¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.ordering.
GeoSpatialOrderingFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Geo-spatial ordering filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> GeoSpatialOrderingFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [GeoSpatialOrderingFilterBackend,] >>> geo_spatial_ordering_fields = { >>> 'location': { >>> 'field': 'location', >>> } >>> }
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
get_geo_distance_params
(value, field)[source]¶ Get params for geo_distance ordering.
Example:
/api/articles/?ordering=-location__45.3214__-34.3421__km__planesParameters: - value (str) –
- field –
Returns: Params to be used in geo_distance query.
Return type: dict
-
get_geo_spatial_field_name
(request, view, name)[source]¶ Get geo-spatial field name.
We have to deal with a couple of situations here:
Example 1:
>>> geo_spatial_ordering_fields = { >>> 'location': None, >>> }
Example 2:
>>> geo_spatial_ordering_fields = { >>> 'location': 'location', >>> }
Example 3:
>>> geo_spatial_ordering_fields = { >>> 'location': { >>> 'field': 'location' >>> }, >>> }
Parameters: - request –
- view –
- name –
Returns:
-
get_ordering_query_params
(request, view)[source]¶ Get ordering query params.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Ordering params to be used for ordering.
Return type: list
-
ordering_param
= 'ordering'¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.ordering.
OrderingFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.ordering.common.OrderingMixin
Ordering filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> OrderingFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [OrderingFilterBackend,] >>> ordering_fields = { >>> 'id': None, >>> 'title': 'title.raw', >>> 'date_submitted': 'date_submitted', >>> 'continent': { >>> 'field': 'continent.name.raw', >>> 'path': 'continent', >>> } >>> 'country': { >>> 'field': 'continent.country.name.raw', >>> 'path': 'continent.country', >>> } >>> 'city': { >>> 'field': 'continent.country.city.name.raw', >>> 'path': 'continent.country.city', >>> } >>> } >>> ordering = ('id', 'title',)
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_ordering_query_params
(request, view)[source]¶ Get ordering query params.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Ordering params to be used for ordering.
Return type: list
-
ordering_param
= 'ordering'¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.match.
MatchQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Match query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'match'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.match_phrase.
MatchPhraseQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Match phrase query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'match_phrase'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.match_phrase_prefix.
MatchPhrasePrefixQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Match phrase prefix query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'match_phrase_prefix'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.multi_match.
MultiMatchQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Multi match query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
In case of multi match, we always look in a group of fields. Thus, matching per field is no longer valid use case here. However, we might want to have multiple fields enabled for multi match per view set, and only search in some of them in specific request.
Example:
/search/books/?search_multi_match=lorem ipsum /search/books/?search_multi_match=title,summary:lorem ipsumNote, that multiple searches are not supported (would not raise an exception, but would simply take only the first):
- /search/books/?search_multi_match=title,summary:lorem ipsum
- &search_multi_match=author,publisher=o’reily
In the view-set fields shall be defined in a very simple way. The only accepted argument would be boost (per field).
Example 1 (complex):
- multi_match_search_fields = {
- ‘title’: {‘field’: ‘title.english’, ‘boost’: 4}, ‘summary’: {‘boost’: 2}, ‘description’: None,
}
Example 2 (simple list):
- multi_match_search_fields = (
- ‘title’, ‘summary’, ‘description’,
)
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'multi_match'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.nested.
NestedQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Nested query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
Dictionary key is the GET param name. The path option stands for the path in Elasticsearch.
Type 1:
- search_nested_fields = {
- ‘country’: {
- ‘path’: ‘country’, ‘fields’: [‘name’],
}, ‘city’: {
‘path’: ‘country.city’, ‘fields’: [‘name’],},
}
Type 2:
- search_nested_fields = {
- ‘country’: {
- ‘path’: ‘country’, ‘fields’: [{‘name’: {‘boost’: 2}}]
}, ‘city’: {
‘path’: ‘country.city’, ‘fields’: [{‘name’: {‘boost’: 2}}]},
}
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'nested'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.simple_query_string.
SimpleQueryStringQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Simple query string query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
In case of multi match, we always look in a group of fields. Thus, matching per field is no longer valid use case here. However, we might want to have multiple fields enabled for multi match per view set, and only search in some of them in specific request.
Example:
- /search/books/?search_simple_query_string=
- “fried eggs” %2B(eggplant | potato) -frittata
- /search/books/?search_simple_query_string=
- title,summary:”fried eggs” +(eggplant | potato) -frittata
Note, that multiple searches are not supported (would not raise an exception, but would simply take only the first):
- /search/books/?search_simple_query_string=
- title,summary:”fried eggs” +(eggplant | potato) -frittata &search_simple_query_string= author,publisher=”fried eggs” +(eggplant | potato) -frittata
In the view-set fields shall be defined in a very simple way. The only accepted argument would be boost (per field).
Example 1 (complex):
- simple_query_string_search_fields = {
- ‘title’: {‘field’: ‘title.english’, ‘boost’: 4}, ‘summary’: {‘boost’: 2}, ‘description’: None,
}
Example 2 (simple list):
- simple_query_string_search_fields = (
- ‘title’, ‘summary’, ‘description’,
)
Query examples:
- http://localhost:8000/search
- /books-simple-query-string-search-backend /?search_simple_query_string=%22Pool%20of%20Tears%22
- http://localhost:8000/search
- /books-simple-query-string-search-backend /?search_simple_query_string=%22Pool%20of%20Tears%22 -considering
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'simple_query_string'¶
-
classmethod
Search query backends.
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.
BaseSearchQueryBackend
[source]¶ Bases:
object
Search query backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.
MatchQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Match query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'match'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.
MatchPhraseQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Match phrase query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'match_phrase'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.
MatchPhrasePrefixQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Match phrase prefix query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'match_phrase_prefix'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.
MultiMatchQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Multi match query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
In case of multi match, we always look in a group of fields. Thus, matching per field is no longer valid use case here. However, we might want to have multiple fields enabled for multi match per view set, and only search in some of them in specific request.
Example:
/search/books/?search_multi_match=lorem ipsum /search/books/?search_multi_match=title,summary:lorem ipsumNote, that multiple searches are not supported (would not raise an exception, but would simply take only the first):
- /search/books/?search_multi_match=title,summary:lorem ipsum
- &search_multi_match=author,publisher=o’reily
In the view-set fields shall be defined in a very simple way. The only accepted argument would be boost (per field).
Example 1 (complex):
- multi_match_search_fields = {
- ‘title’: {‘field’: ‘title.english’, ‘boost’: 4}, ‘summary’: {‘boost’: 2}, ‘description’: None,
}
Example 2 (simple list):
- multi_match_search_fields = (
- ‘title’, ‘summary’, ‘description’,
)
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'multi_match'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.
NestedQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Nested query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
Dictionary key is the GET param name. The path option stands for the path in Elasticsearch.
Type 1:
- search_nested_fields = {
- ‘country’: {
- ‘path’: ‘country’, ‘fields’: [‘name’],
}, ‘city’: {
‘path’: ‘country.city’, ‘fields’: [‘name’],},
}
Type 2:
- search_nested_fields = {
- ‘country’: {
- ‘path’: ‘country’, ‘fields’: [{‘name’: {‘boost’: 2}}]
}, ‘city’: {
‘path’: ‘country.city’, ‘fields’: [{‘name’: {‘boost’: 2}}]},
}
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'nested'¶
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.
SimpleQueryStringQueryBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.query_backends.base.BaseSearchQueryBackend
Simple query string query backend.
-
classmethod
construct_search
(request, view, search_backend)[source]¶ Construct search.
In case of multi match, we always look in a group of fields. Thus, matching per field is no longer valid use case here. However, we might want to have multiple fields enabled for multi match per view set, and only search in some of them in specific request.
Example:
- /search/books/?search_simple_query_string=
- “fried eggs” %2B(eggplant | potato) -frittata
- /search/books/?search_simple_query_string=
- title,summary:”fried eggs” +(eggplant | potato) -frittata
Note, that multiple searches are not supported (would not raise an exception, but would simply take only the first):
- /search/books/?search_simple_query_string=
- title,summary:”fried eggs” +(eggplant | potato) -frittata &search_simple_query_string= author,publisher=”fried eggs” +(eggplant | potato) -frittata
In the view-set fields shall be defined in a very simple way. The only accepted argument would be boost (per field).
Example 1 (complex):
- simple_query_string_search_fields = {
- ‘title’: {‘field’: ‘title.english’, ‘boost’: 4}, ‘summary’: {‘boost’: 2}, ‘description’: None,
}
Example 2 (simple list):
- simple_query_string_search_fields = (
- ‘title’, ‘summary’, ‘description’,
)
Query examples:
- http://localhost:8000/search
- /books-simple-query-string-search-backend /?search_simple_query_string=%22Pool%20of%20Tears%22
- http://localhost:8000/search
- /books-simple-query-string-search-backend /?search_simple_query_string=%22Pool%20of%20Tears%22 -considering
Parameters: - request –
- view –
- search_backend –
Returns:
-
query_type
= 'simple_query_string'¶
-
classmethod
Base search backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.search.base.
BaseSearchFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Base search filter backend.
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_search_query_params
(request)[source]¶ Get search query params.
Parameters: request (rest_framework.request.Request) – Django REST framework request. Returns: List of search query params. Return type: list
-
matching
= 'should'¶
-
query_backends
= []¶
-
search_param
= 'search'¶
-
Compound search backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.search.compound.
CompoundSearchFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.base.BaseSearchFilterBackend
Compound search backend.
-
query_backends
= [<class 'django_elasticsearch_dsl_drf.filter_backends.search.query_backends.match.MatchQueryBackend'>, <class 'django_elasticsearch_dsl_drf.filter_backends.search.query_backends.nested.NestedQueryBackend'>]¶
-
Search backend. Most likely to be deprecated soon.
-
class
django_elasticsearch_dsl_drf.filter_backends.search.historical.
SearchFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Search filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> SearchFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [SearchFilterBackend,] >>> search_fields = ( >>> 'title', >>> 'content', >>> ) >>> search_nested_fields = { >>> 'state': ['name'], >>> 'documents.author': ['title', 'description'], >>> }
-
construct_nested_search
(request, view)[source]¶ Construct nested search.
We have to deal with two types of structures:
Type 1:
>>> search_nested_fields = { >>> 'country': { >>> 'path': 'country', >>> 'fields': ['name'], >>> }, >>> 'city': { >>> 'path': 'country.city', >>> 'fields': ['name'], >>> }, >>> }
Type 2:
>>> search_nested_fields = { >>> 'country': { >>> 'path': 'country', >>> 'fields': [{'name': {'boost': 2}}] >>> }, >>> 'city': { >>> 'path': 'country.city', >>> 'fields': [{'name': {'boost': 2}}] >>> }, >>> }
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
construct_search
(request, view)[source]¶ Construct search.
We have to deal with two types of structures:
Type 1:
>>> search_fields = ( >>> 'title', >>> 'description', >>> 'summary', >>> )
Type 2:
>>> search_fields = { >>> 'title': {'boost': 2}, >>> 'description': None, >>> 'summary': None, >>> }
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_search_query_params
(request)[source]¶ Get search query params.
Parameters: request (rest_framework.request.Request) – Django REST framework request. Returns: List of search query params. Return type: list
-
search_param
= 'search'¶
-
Multi match search filter backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.search.multi_match.
MultiMatchSearchFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.base.BaseSearchFilterBackend
Multi match search filter backend.
-
matching
= 'must'¶
-
query_backends
= [<class 'django_elasticsearch_dsl_drf.filter_backends.search.query_backends.multi_match.MultiMatchQueryBackend'>]¶
-
search_param
= 'search_multi_match'¶
-
Simple query string search filter backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.search.simple_query_string.
SimpleQueryStringSearchFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.base.BaseSearchFilterBackend
Simple query string search filter backend.
-
matching
= 'must'¶
-
query_backends
= [<class 'django_elasticsearch_dsl_drf.filter_backends.search.query_backends.simple_query_string.SimpleQueryStringQueryBackend'>]¶
-
search_param
= 'search_simple_query_string'¶
-
Search filter backends.
-
class
django_elasticsearch_dsl_drf.filter_backends.search.
BaseSearchFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Base search filter backend.
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_search_query_params
(request)[source]¶ Get search query params.
Parameters: request (rest_framework.request.Request) – Django REST framework request. Returns: List of search query params. Return type: list
-
matching
= 'should'¶
-
query_backends
= []¶
-
search_param
= 'search'¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.search.
CompoundSearchFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.base.BaseSearchFilterBackend
Compound search backend.
-
query_backends
= [<class 'django_elasticsearch_dsl_drf.filter_backends.search.query_backends.match.MatchQueryBackend'>, <class 'django_elasticsearch_dsl_drf.filter_backends.search.query_backends.nested.NestedQueryBackend'>]¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.search.
MultiMatchSearchFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.base.BaseSearchFilterBackend
Multi match search filter backend.
-
matching
= 'must'¶
-
query_backends
= [<class 'django_elasticsearch_dsl_drf.filter_backends.search.query_backends.multi_match.MultiMatchQueryBackend'>]¶
-
search_param
= 'search_multi_match'¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.search.
SearchFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Search filter backend for Elasticsearch.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> SearchFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [SearchFilterBackend,] >>> search_fields = ( >>> 'title', >>> 'content', >>> ) >>> search_nested_fields = { >>> 'state': ['name'], >>> 'documents.author': ['title', 'description'], >>> }
-
construct_nested_search
(request, view)[source]¶ Construct nested search.
We have to deal with two types of structures:
Type 1:
>>> search_nested_fields = { >>> 'country': { >>> 'path': 'country', >>> 'fields': ['name'], >>> }, >>> 'city': { >>> 'path': 'country.city', >>> 'fields': ['name'], >>> }, >>> }
Type 2:
>>> search_nested_fields = { >>> 'country': { >>> 'path': 'country', >>> 'fields': [{'name': {'boost': 2}}] >>> }, >>> 'city': { >>> 'path': 'country.city', >>> 'fields': [{'name': {'boost': 2}}] >>> }, >>> }
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
construct_search
(request, view)[source]¶ Construct search.
We have to deal with two types of structures:
Type 1:
>>> search_fields = ( >>> 'title', >>> 'description', >>> 'summary', >>> )
Type 2:
>>> search_fields = { >>> 'title': {'boost': 2}, >>> 'description': None, >>> 'summary': None, >>> }
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_search_query_params
(request)[source]¶ Get search query params.
Parameters: request (rest_framework.request.Request) – Django REST framework request. Returns: List of search query params. Return type: list
-
search_param
= 'search'¶
-
-
class
django_elasticsearch_dsl_drf.filter_backends.search.
SimpleQueryStringSearchFilterBackend
[source]¶ Bases:
django_elasticsearch_dsl_drf.filter_backends.search.base.BaseSearchFilterBackend
Simple query string search filter backend.
-
matching
= 'must'¶
-
query_backends
= [<class 'django_elasticsearch_dsl_drf.filter_backends.search.query_backends.simple_query_string.SimpleQueryStringQueryBackend'>]¶
-
search_param
= 'search_simple_query_string'¶
-
Functional suggesters backend.
It’s assumed, that fields you’re planning to query suggestions for have been
properly indexed using fields.CompletionField
.
Example:
>>> from django_elasticsearch_dsl import DocType, Index, fields
>>>
>>> from books.models import Publisher
>>>
>>> # Name of the Elasticsearch index
>>> PUBLISHER_INDEX = Index(PUBLISHER_INDEX_NAME)
>>> # See Elasticsearch Indices API reference for available settings
>>> PUBLISHER_INDEX.settings(
>>> number_of_shards=1,
>>> number_of_replicas=1
>>> )
>>>
>>> @PUBLISHER_INDEX.doc_type
>>> class PublisherDocument(DocType):
>>> "Publisher Elasticsearch document."
>>>
>>> id = fields.IntegerField(attr='id')
>>>
>>> name = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword'),
>>> 'suggest': fields.CompletionField(),
>>> }
>>> )
>>>
>>> info = fields.StringField()
>>>
>>> address = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword')
>>> }
>>> )
>>>
>>> city = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword'),
>>> 'suggest': fields.CompletionField(),
>>> }
>>> )
>>>
>>> state_province = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword'),
>>> 'suggest': fields.CompletionField(),
>>> }
>>> )
>>>
>>> country = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword'),
>>> 'suggest': fields.CompletionField(),
>>> }
>>> )
>>>
>>> website = fields.StringField()
>>>
>>> class Meta(object):
>>> "Meta options."
>>>
>>> model = Publisher # The model associate with this DocType
-
class
django_elasticsearch_dsl_drf.filter_backends.suggester.functional.
FunctionalSuggesterFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Suggester filter backend for Elasticsearch.
Suggestion functionality is exclusive. Once you have queried the
FunctionalSuggesterFilterBackend
, the latter will transform your current search query into another search query (altered). Therefore, always add it as the very last filter backend.Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> FUNCTIONAL_SUGGESTER_COMPLETION_MATCH, >>> FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX, >>> FUNCTIONAL_SUGGESTER_PHRASE_MATCH, >>> FUNCTIONAL_SUGGESTER_PHRASE_MATCH, >>> FUNCTIONAL_SUGGESTER_TERM_MATCH, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> FunctionalSuggesterFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet >>> >>> # Local PublisherDocument definition >>> from .documents import PublisherDocument >>> >>> # Local PublisherDocument serializer >>> from .serializers import PublisherDocumentSerializer >>> >>> class PublisherDocumentView(DocumentViewSet): >>> >>> document = PublisherDocument >>> serializer_class = PublisherDocumentSerializer >>> filter_backends = [ >>> # ... >>> FunctionalSuggesterFilterBackend, >>> ] >>> # Suggester fields >>> functional_suggester_fields = { >>> 'name_suggest': { >>> 'field': 'name.suggest', >>> 'suggesters': [ >>> FUNCTIONAL_SUGGESTER_COMPLETION_MATCH, >>> FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX, >>> ], >>> }, >>> 'city_suggest': { >>> 'field': 'city.suggest', >>> 'suggesters': [ >>> FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX, >>> ], >>> }, >>> 'state_province_suggest': { >>> 'field': 'state_province.suggest', >>> 'suggesters': [ >>> FUNCTIONAL_SUGGESTER_COMPLETION_MATCH, >>> ], >>> }, >>> 'country_suggest': { >>> 'field': 'country.suggest', >>> 'suggesters': [ >>> FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX, >>> ], >>> }, >>> }
-
classmethod
apply_query_size
(queryset, options)[source]¶ Apply query size.
Parameters: - queryset –
- options –
Returns:
-
classmethod
apply_suggester_completion_match
(suggester_name, queryset, options, value)[source]¶ Apply completion suggester match.
This is effective when used with Ngram fields.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_suggester_completion_prefix
(suggester_name, queryset, options, value)[source]¶ Apply completion suggester prefix.
This is effective when used with Keyword fields.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
clean_queryset
(queryset)[source]¶ Clean the queryset.
- Remove aggregations.
- Remove highlight.
- Remove sorting options.
Parameters: queryset – Returns:
-
extract_field_name
(field_name)[source]¶ Extract field name.
For instance, “name.suggest” or “name.raw” becomes “name”.
Parameters: field_name – Returns: Return type: str
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_suggester_query_params
(request, view)[source]¶ Get query params to be for suggestions.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Request query params to filter on.
Return type: dict
-
classmethod
Suggesters backend.
It’s assumed, that fields you’re planning to query suggestions for have been
properly indexed using fields.CompletionField
.
Example:
>>> from django_elasticsearch_dsl import DocType, Index, fields
>>>
>>> from books.models import Publisher
>>>
>>> # Name of the Elasticsearch index
>>> PUBLISHER_INDEX = Index(PUBLISHER_INDEX_NAME)
>>> # See Elasticsearch Indices API reference for available settings
>>> PUBLISHER_INDEX.settings(
>>> number_of_shards=1,
>>> number_of_replicas=1
>>> )
>>>
>>> @PUBLISHER_INDEX.doc_type
>>> class PublisherDocument(DocType):
>>> "Publisher Elasticsearch document."
>>>
>>> id = fields.IntegerField(attr='id')
>>>
>>> name = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword'),
>>> 'suggest': fields.CompletionField(),
>>> }
>>> )
>>>
>>> info = fields.StringField()
>>>
>>> address = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword')
>>> }
>>> )
>>>
>>> city = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword'),
>>> 'suggest': fields.CompletionField(),
>>> }
>>> )
>>>
>>> state_province = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword'),
>>> 'suggest': fields.CompletionField(),
>>> }
>>> )
>>>
>>> country = fields.StringField(
>>> fields={
>>> 'raw': fields.StringField(analyzer='keyword'),
>>> 'suggest': fields.CompletionField(),
>>> }
>>> )
>>>
>>> website = fields.StringField()
>>>
>>> class Meta(object):
>>> "Meta options."
>>>
>>> model = Publisher # The model associate with this DocType
-
class
django_elasticsearch_dsl_drf.filter_backends.suggester.native.
SuggesterFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Suggester filter backend for Elasticsearch.
Suggestion functionality is exclusive. Once you have queried the
SuggesterFilterBackend
, the latter will transform your current search query into suggestion search query (which is very different). Therefore, always add it as the very last filter backend.Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> SUGGESTER_TERM, >>> SUGGESTER_PHRASE, >>> SUGGESTER_COMPLETION, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> SuggesterFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet >>> >>> # Local PublisherDocument definition >>> from .documents import PublisherDocument >>> >>> # Local PublisherDocument serializer >>> from .serializers import PublisherDocumentSerializer >>> >>> class PublisherDocumentView(BaseDocumentViewSet): >>> >>> document = PublisherDocument >>> serializer_class = PublisherDocumentSerializer >>> filter_backends = [ >>> # ... >>> SuggesterFilterBackend, >>> ] >>> # Suggester fields >>> suggester_fields = { >>> 'name_suggest': { >>> 'field': 'name.suggest', >>> 'suggesters': [ >>> SUGGESTER_TERM, >>> SUGGESTER_PHRASE, >>> SUGGESTER_COMPLETION, >>> ], >>> }, >>> 'city_suggest': { >>> 'field': 'city.suggest', >>> 'suggesters': [ >>> SUGGESTER_COMPLETION, >>> ], >>> }, >>> 'state_province_suggest': { >>> 'field': 'state_province.suggest', >>> 'suggesters': [ >>> SUGGESTER_COMPLETION, >>> ], >>> }, >>> 'country_suggest': { >>> 'field': 'country.suggest', >>> 'suggesters': [ >>> SUGGESTER_COMPLETION, >>> ], >>> }, >>> }
-
classmethod
apply_suggester_completion
(suggester_name, queryset, options, value)[source]¶ Apply completion suggester.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_suggester_phrase
(suggester_name, queryset, options, value)[source]¶ Apply phrase suggester.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_suggester_term
(suggester_name, queryset, options, value)[source]¶ Apply term suggester.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
get_suggester_context
(field, suggester_name, request, view)[source]¶ Get suggester context.
Given the following definition (in ViewSets):
>>> # Suggester fields >>> suggester_fields = { >>> 'title_suggest': { >>> 'field': 'title.suggest', >>> 'default_suggester': SUGGESTER_COMPLETION, >>> }, >>> 'title_suggest_context': { >>> 'field': 'title.suggest_context', >>> 'default_suggester': SUGGESTER_COMPLETION, >>> 'completion_options': { >>> 'filters': { >>> 'title_suggest_tag': 'tag', >>> 'title_suggest_state': 'state', >>> 'title_suggest_publisher': 'publisher', >>> }, >>> 'size': 10, >>> } >>> }, >>> }
http://localhost:8000/search/books-frontend/suggest/?title_suggest_context=M
When talking about the queries made, we have the following. Multiple values per field are combined with OR:
>>> completion={ >>> 'field': options['field'], >>> 'size': 10, >>> 'contexts': { >>> 'tag': ['History', 'Drama'], >>> } >>> }
The following works with OR as well, so it seems we have OR only. However, the following construction is more handy, since it allows us to play with boosting nicely. Also, it allows to provide prefix param (which in case of the example given below means that suggestions shall match both categories with “Child”, “Children”, “Childrend’s”). Simply put it’s treated as prefix, rather than term.
>>> completion={ >>> 'field': options['field'], >>> 'size': 10, >>> 'contexts': { >>> 'tag': [ >>> {'context': 'History'}, >>> {'context': 'Drama', 'boost': 2}, >>> {'context': 'Children', 'prefix': True}, >>> ], >>> }, >>> }
Sample query for category filter:
/search/books-frontend/suggest/ ?title_suggest_context=M &title_suggest_tag=Art__2.0 &title_suggest_tag=Documentary__2.0__prefix &title_suggest_publisher=ApressThe query params would be:
query_params: <QueryDict: {
‘title_suggest_context’: [‘M’], ‘title_suggest_tag’: [‘Art__2.0’, ‘Documentary__2.0__prefix’], ‘title_suggest_publisher’: [‘Apress’]}>
Sample query for geo filter:
/search/address/suggest/ ?street_suggest_context=M &street_suggest_loc=43.66__-79.22__2.0__10000kmThe query params would be:
query_params: <QueryDict: {
‘street_suggest_context’: [‘M’], ‘street_suggest_loc’: [‘Art__43.66__-79.22__2.0__10000km’],}>
Returns:
-
classmethod
Suggester filtering backends.
-
class
django_elasticsearch_dsl_drf.filter_backends.suggester.
SuggesterFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Suggester filter backend for Elasticsearch.
Suggestion functionality is exclusive. Once you have queried the
SuggesterFilterBackend
, the latter will transform your current search query into suggestion search query (which is very different). Therefore, always add it as the very last filter backend.Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> SUGGESTER_TERM, >>> SUGGESTER_PHRASE, >>> SUGGESTER_COMPLETION, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> SuggesterFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet >>> >>> # Local PublisherDocument definition >>> from .documents import PublisherDocument >>> >>> # Local PublisherDocument serializer >>> from .serializers import PublisherDocumentSerializer >>> >>> class PublisherDocumentView(BaseDocumentViewSet): >>> >>> document = PublisherDocument >>> serializer_class = PublisherDocumentSerializer >>> filter_backends = [ >>> # ... >>> SuggesterFilterBackend, >>> ] >>> # Suggester fields >>> suggester_fields = { >>> 'name_suggest': { >>> 'field': 'name.suggest', >>> 'suggesters': [ >>> SUGGESTER_TERM, >>> SUGGESTER_PHRASE, >>> SUGGESTER_COMPLETION, >>> ], >>> }, >>> 'city_suggest': { >>> 'field': 'city.suggest', >>> 'suggesters': [ >>> SUGGESTER_COMPLETION, >>> ], >>> }, >>> 'state_province_suggest': { >>> 'field': 'state_province.suggest', >>> 'suggesters': [ >>> SUGGESTER_COMPLETION, >>> ], >>> }, >>> 'country_suggest': { >>> 'field': 'country.suggest', >>> 'suggesters': [ >>> SUGGESTER_COMPLETION, >>> ], >>> }, >>> }
-
classmethod
apply_suggester_completion
(suggester_name, queryset, options, value)[source]¶ Apply completion suggester.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_suggester_phrase
(suggester_name, queryset, options, value)[source]¶ Apply phrase suggester.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_suggester_term
(suggester_name, queryset, options, value)[source]¶ Apply term suggester.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
get_suggester_context
(field, suggester_name, request, view)[source]¶ Get suggester context.
Given the following definition (in ViewSets):
>>> # Suggester fields >>> suggester_fields = { >>> 'title_suggest': { >>> 'field': 'title.suggest', >>> 'default_suggester': SUGGESTER_COMPLETION, >>> }, >>> 'title_suggest_context': { >>> 'field': 'title.suggest_context', >>> 'default_suggester': SUGGESTER_COMPLETION, >>> 'completion_options': { >>> 'filters': { >>> 'title_suggest_tag': 'tag', >>> 'title_suggest_state': 'state', >>> 'title_suggest_publisher': 'publisher', >>> }, >>> 'size': 10, >>> } >>> }, >>> }
http://localhost:8000/search/books-frontend/suggest/?title_suggest_context=M
When talking about the queries made, we have the following. Multiple values per field are combined with OR:
>>> completion={ >>> 'field': options['field'], >>> 'size': 10, >>> 'contexts': { >>> 'tag': ['History', 'Drama'], >>> } >>> }
The following works with OR as well, so it seems we have OR only. However, the following construction is more handy, since it allows us to play with boosting nicely. Also, it allows to provide prefix param (which in case of the example given below means that suggestions shall match both categories with “Child”, “Children”, “Childrend’s”). Simply put it’s treated as prefix, rather than term.
>>> completion={ >>> 'field': options['field'], >>> 'size': 10, >>> 'contexts': { >>> 'tag': [ >>> {'context': 'History'}, >>> {'context': 'Drama', 'boost': 2}, >>> {'context': 'Children', 'prefix': True}, >>> ], >>> }, >>> }
Sample query for category filter:
/search/books-frontend/suggest/ ?title_suggest_context=M &title_suggest_tag=Art__2.0 &title_suggest_tag=Documentary__2.0__prefix &title_suggest_publisher=ApressThe query params would be:
query_params: <QueryDict: {
‘title_suggest_context’: [‘M’], ‘title_suggest_tag’: [‘Art__2.0’, ‘Documentary__2.0__prefix’], ‘title_suggest_publisher’: [‘Apress’]}>
Sample query for geo filter:
/search/address/suggest/ ?street_suggest_context=M &street_suggest_loc=43.66__-79.22__2.0__10000kmThe query params would be:
query_params: <QueryDict: {
‘street_suggest_context’: [‘M’], ‘street_suggest_loc’: [‘Art__43.66__-79.22__2.0__10000km’],}>
Returns:
-
classmethod
-
class
django_elasticsearch_dsl_drf.filter_backends.suggester.
FunctionalSuggesterFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
,django_elasticsearch_dsl_drf.filter_backends.mixins.FilterBackendMixin
Suggester filter backend for Elasticsearch.
Suggestion functionality is exclusive. Once you have queried the
FunctionalSuggesterFilterBackend
, the latter will transform your current search query into another search query (altered). Therefore, always add it as the very last filter backend.Example:
>>> from django_elasticsearch_dsl_drf.constants import ( >>> FUNCTIONAL_SUGGESTER_COMPLETION_MATCH, >>> FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX, >>> FUNCTIONAL_SUGGESTER_PHRASE_MATCH, >>> FUNCTIONAL_SUGGESTER_PHRASE_MATCH, >>> FUNCTIONAL_SUGGESTER_TERM_MATCH, >>> ) >>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> FunctionalSuggesterFilterBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import DocumentViewSet >>> >>> # Local PublisherDocument definition >>> from .documents import PublisherDocument >>> >>> # Local PublisherDocument serializer >>> from .serializers import PublisherDocumentSerializer >>> >>> class PublisherDocumentView(DocumentViewSet): >>> >>> document = PublisherDocument >>> serializer_class = PublisherDocumentSerializer >>> filter_backends = [ >>> # ... >>> FunctionalSuggesterFilterBackend, >>> ] >>> # Suggester fields >>> functional_suggester_fields = { >>> 'name_suggest': { >>> 'field': 'name.suggest', >>> 'suggesters': [ >>> FUNCTIONAL_SUGGESTER_COMPLETION_MATCH, >>> FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX, >>> ], >>> }, >>> 'city_suggest': { >>> 'field': 'city.suggest', >>> 'suggesters': [ >>> FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX, >>> ], >>> }, >>> 'state_province_suggest': { >>> 'field': 'state_province.suggest', >>> 'suggesters': [ >>> FUNCTIONAL_SUGGESTER_COMPLETION_MATCH, >>> ], >>> }, >>> 'country_suggest': { >>> 'field': 'country.suggest', >>> 'suggesters': [ >>> FUNCTIONAL_SUGGESTER_COMPLETION_PREFIX, >>> ], >>> }, >>> }
-
classmethod
apply_query_size
(queryset, options)[source]¶ Apply query size.
Parameters: - queryset –
- options –
Returns:
-
classmethod
apply_suggester_completion_match
(suggester_name, queryset, options, value)[source]¶ Apply completion suggester match.
This is effective when used with Ngram fields.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
classmethod
apply_suggester_completion_prefix
(suggester_name, queryset, options, value)[source]¶ Apply completion suggester prefix.
This is effective when used with Keyword fields.
Parameters: - suggester_name (str) –
- queryset (elasticsearch_dsl.search.Search) – Original queryset.
- options (dict) – Filter options.
- value (str) – value to filter on.
Returns: Modified queryset.
Return type: elasticsearch_dsl.search.Search
-
clean_queryset
(queryset)[source]¶ Clean the queryset.
- Remove aggregations.
- Remove highlight.
- Remove sorting options.
Parameters: queryset – Returns:
-
extract_field_name
(field_name)[source]¶ Extract field name.
For instance, “name.suggest” or “name.raw” becomes “name”.
Parameters: field_name – Returns: Return type: str
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_suggester_query_params
(request, view)[source]¶ Get query params to be for suggestions.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Request query params to filter on.
Return type: dict
-
classmethod
Submodules¶
django_elasticsearch_dsl_drf.filter_backends.faceted_search module¶
Faceted search backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.faceted_search.
FacetedSearchFilterBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
Faceted search backend.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> FacetedSearchFilterBackend >>> ) >>> from elasticsearch_dsl import TermsFacet, DateHistogramFacet >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [FacetedSearchFilterBackend,] >>> faceted_search_fields = { >>> 'title': 'title.raw', # Uses `TermsFacet` by default >>> 'state': { >>> 'field': 'state.raw', >>> 'facet': TermsFacet, >>> }, >>> 'publisher': { >>> 'field': 'publisher.raw', >>> 'facet': TermsFacet, >>> 'enabled': False, >>> }, >>> 'date_published': { >>> 'field': 'date_published.raw', >>> 'facet': DateHistogramFacet, >>> 'options': { >>> 'interval': 'month', >>> }, >>> 'enabled': True, >>> }, >>> >>> }
Facets make queries to be more heavy. That’s why by default all facets are disabled and enabled only explicitly either in the filter options (enabled set to True) or via query params ?facet=state&facet=date_published.
-
aggregate
(request, queryset, view)[source]¶ Aggregate.
Parameters: - request –
- queryset –
- view –
Returns:
-
construct_facets
(request, view)[source]¶ Construct facets.
Turns the following structure:
>>> { >>> 'publisher': { >>> 'field': 'publisher.raw', >>> 'facet': TermsFacet, >>> 'enabled': False, >>> } >>> 'date_published': { >>> 'field': 'date_published', >>> 'facet': DateHistogramFacet, >>> 'options': { >>> 'interval': 'month', >>> }, >>> 'enabled': True, >>> }, >>> }
Into the following structure:
>>> { >>> 'publisher': TermsFacet(field='publisher.raw'), >>> 'publishing_frequency': DateHistogramFacet( >>> field='date_published.raw', >>> interval='month' >>> ), >>> }
-
faceted_search_param
= 'facet'¶
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_faceted_search_query_params
(request)[source]¶ Get faceted search query params.
Parameters: request (rest_framework.request.Request) – Django REST framework request. Returns: List of search query params. Return type: list
-
classmethod
prepare_faceted_search_fields
(view)[source]¶ Prepare faceted search fields.
Prepares the following structure:
>>> { >>> 'publisher': { >>> 'field': 'publisher.raw', >>> 'facet': TermsFacet, >>> 'enabled': False, >>> } >>> 'date_published': { >>> 'field': 'date_published.raw', >>> 'facet': DateHistogramFacet, >>> 'options': { >>> 'interval': 'month', >>> }, >>> 'enabled': True, >>> }, >>> }
Parameters: view (rest_framework.viewsets.ReadOnlyModelViewSet) – Returns: Faceted search fields options. Return type: dict
-
django_elasticsearch_dsl_drf.filter_backends.highlight module¶
Highlight backend.
-
class
django_elasticsearch_dsl_drf.filter_backends.highlight.
HighlightBackend
[source]¶ Bases:
rest_framework.filters.BaseFilterBackend
Highlight backend.
Example:
>>> from django_elasticsearch_dsl_drf.filter_backends import ( >>> HighlightBackend >>> ) >>> from django_elasticsearch_dsl_drf.viewsets import ( >>> BaseDocumentViewSet, >>> ) >>> >>> # Local article document definition >>> from .documents import ArticleDocument >>> >>> # Local article document serializer >>> from .serializers import ArticleDocumentSerializer >>> >>> class ArticleDocumentView(BaseDocumentViewSet): >>> >>> document = ArticleDocument >>> serializer_class = ArticleDocumentSerializer >>> filter_backends = [HighlightBackend,] >>> highlight_fields = { >>> 'author.name': { >>> 'enabled': False, >>> 'options': { >>> 'fragment_size': 150, >>> 'number_of_fragments': 3 >>> } >>> } >>> 'title': { >>> 'options': { >>> 'pre_tags' : ["<em>"], >>> 'post_tags' : ["</em>"] >>> }, >>> 'enabled': True, >>> }, >>> }
Highlight make queries to be more heavy. That’s why by default all highlights are disabled and enabled only explicitly either in the filter options (enabled set to True) or via query params ?highlight=author.name&highlight=title.
-
filter_queryset
(request, queryset, view)[source]¶ Filter the queryset.
Parameters: - request (rest_framework.request.Request) – Django REST framework request.
- queryset (elasticsearch_dsl.search.Search) – Base queryset.
- view (rest_framework.viewsets.ReadOnlyModelViewSet) – View.
Returns: Updated queryset.
Return type: elasticsearch_dsl.search.Search
-
get_highlight_query_params
(request)[source]¶ Get highlight query params.
Parameters: request (rest_framework.request.Request) – Django REST framework request. Returns: List of search query params. Return type: list
-
highlight_param
= 'highlight'¶
-
classmethod
prepare_highlight_fields
(view)[source]¶ Prepare faceted search fields.
Prepares the following structure:
>>> { >>> 'author.name': { >>> 'enabled': False, >>> 'options': { >>> 'fragment_size': 150, >>> 'number_of_fragments': 3 >>> } >>> } >>> 'title': { >>> 'options': { >>> 'pre_tags' : ["<em>"], >>> 'post_tags' : ["</em>"] >>> }, >>> 'enabled': True, >>> }, >>> }
Parameters: view (rest_framework.viewsets.ReadOnlyModelViewSet) – Returns: Highlight fields options. Return type: dict
-
django_elasticsearch_dsl_drf.filter_backends.mixins module¶
Mixins.
-
class
django_elasticsearch_dsl_drf.filter_backends.mixins.
FilterBackendMixin
[source]¶ Bases:
object
Filter backend mixin.
-
classmethod
apply_filter
(queryset, options=None, args=None, kwargs=None)[source]¶ Apply filter.
Parameters: - queryset –
- options –
- args –
- kwargs –
Returns:
-
classmethod
apply_query
(queryset, options=None, args=None, kwargs=None)[source]¶ Apply query.
Parameters: - queryset –
- options –
- args –
- kwargs –
Returns:
-
classmethod
split_lookup_complex_multiple_value
(value, maxsplit=-1)[source]¶ Split lookup complex multiple value.
Parameters: - value (str) – Value to split.
- maxsplit (int) – The maxsplit option of string.split.
Returns: Lookup filter split into a list.
Return type: list
-
classmethod
split_lookup_complex_value
(value, maxsplit=-1)[source]¶ Split lookup complex value.
Parameters: - value (str) – Value to split.
- maxsplit (int) – The maxsplit option of string.split.
Returns: Lookup filter split into a list.
Return type: list
-
classmethod
Module contents¶
All filter backends.
django_elasticsearch_dsl_drf.tests package¶
Submodules¶
django_elasticsearch_dsl_drf.tests.base module¶
Base tests.
-
class
django_elasticsearch_dsl_drf.tests.base.
BaseRestFrameworkTestCase
(methodName='runTest')[source]¶ Bases:
django.test.testcases.TransactionTestCase
Base REST framework test case.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.data_mixins module¶
Data mixins.
django_elasticsearch_dsl_drf.tests.test_faceted_search module¶
Test faceted search backend.
-
class
django_elasticsearch_dsl_drf.tests.test_faceted_search.
TestFacetedSearch
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test faceted search.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_filtering_common module¶
Test filtering backend.
-
class
django_elasticsearch_dsl_drf.tests.test_filtering_common.
TestFilteringCommon
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
,django_elasticsearch_dsl_drf.tests.data_mixins.BooksMixin
Test filtering common.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
test_default_filter_lookup
()[source]¶ Test default filter lookup.
Example:
- http://localhost:8000/search/books-default-filter-lookup/
- ?authors=Robin&authors=Luc
-
django_elasticsearch_dsl_drf.tests.test_filtering_geo_spatial module¶
Test geo-spatial filtering backend.
-
class
django_elasticsearch_dsl_drf.tests.test_filtering_geo_spatial.
TestFilteringGeoSpatial
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test filtering geo-spatial.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
test_field_filter_geo_bounding_box_fail_test
()[source]¶ Test field filter geo-bounding-box (fail test).
Returns:
-
test_field_filter_geo_distance
()[source]¶ Field filter geo-distance.
Example:
http://localhost:8000 /api/publisher/?location__geo_distance=1km__48.8549__2.3000Returns:
-
test_field_filter_geo_distance_distance_type_arc
()[source]¶ Field filter geo-distance.
Example:
http://localhost:8000 /api/publisher/?location__geo_distance=1km__48.8549__2.3000__arcReturns:
-
test_field_filter_geo_distance_not_enough_args_fail
()[source]¶ Field filter geo-distance. Fail test on not enough args.
Example:
http://localhost:8000 /api/publisher/?location__geo_distance=1km__48.8549Returns:
-
django_elasticsearch_dsl_drf.tests.test_filtering_global_aggregations module¶
Test filtering post_filter backend.
-
class
django_elasticsearch_dsl_drf.tests.test_filtering_global_aggregations.
TestFilteringGlobalAggregations
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
,django_elasticsearch_dsl_drf.tests.data_mixins.BooksMixin
Test filtering with global aggregations.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_filtering_nested module¶
Test nested filtering backend.
-
class
django_elasticsearch_dsl_drf.tests.test_filtering_nested.
TestFilteringNested
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
Test filtering nested.
-
base_url
¶
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_filtering_post_filter module¶
Test filtering post_filter backend.
-
class
django_elasticsearch_dsl_drf.tests.test_filtering_post_filter.
TestFilteringPostFilter
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
,django_elasticsearch_dsl_drf.tests.data_mixins.BooksMixin
Test filtering post_filter.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_functional_suggesters module¶
Test functional suggestions backend.
-
class
django_elasticsearch_dsl_drf.tests.test_functional_suggesters.
TestFunctionalSuggesters
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
Test functional suggesters.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_helpers module¶
Test helpers.
-
class
django_elasticsearch_dsl_drf.tests.test_helpers.
TestHelpers
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseTestCase
Test helpers.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_highlight module¶
Test highlight backend.
-
class
django_elasticsearch_dsl_drf.tests.test_highlight.
TestHighlight
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test highlight.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_more_like_this module¶
Test more-like-this functionality.
-
class
django_elasticsearch_dsl_drf.tests.test_more_like_this.
TestMoreLikeThis
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test suggesters.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_ordering_common module¶
Test ordering backend.
-
class
django_elasticsearch_dsl_drf.tests.test_ordering_common.
TestOrdering
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test ordering.
-
static
deep_get
(dic, keys, default=None)[source]¶ Returns value at period separated keys in dictionary or default
From https://stackoverflow.com/a/46890853
Parameters: - dic (dict) – Dictionary to retrieve value from.
- keys (str) – Period separated path of keys
- default (str) – Default value to return if keys not found
Returns: Value at keys or default
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
test_address_order_by_nested_field_continent_ascending
()[source]¶ Order by field continent.country.name.raw ascending.
-
test_address_order_by_nested_field_continent_descending
()[source]¶ Order by field continent.country.name.raw descending.
-
test_address_order_by_nested_field_country_ascending
()[source]¶ Order by field continent.country.name.raw ascending.
-
test_address_order_by_nested_field_country_descending
()[source]¶ Order by field continent.country.name.raw descending.
Author order by default.
Order by field name ascending.
Order by field id descending.
Order by field name ascending.
Order by field name descending.
-
static
django_elasticsearch_dsl_drf.tests.test_ordering_geo_spatial module¶
Test geo-spatial ordering filter backend.
-
class
django_elasticsearch_dsl_drf.tests.test_ordering_geo_spatial.
TestOrderingGeoSpatial
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test ordering geo-spatial.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
test_field_filter_geo_distance
()[source]¶ Field filter geo_distance.
Example:
http://localhost:8000 /api/publisher/?ordering=location;48.85;2.30;km;plane
-
django_elasticsearch_dsl_drf.tests.test_pagination module¶
Test pagination.
-
class
django_elasticsearch_dsl_drf.tests.test_pagination.
TestPagination
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test pagination.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_pip_helpers module¶
Test pip_helpers.
-
class
django_elasticsearch_dsl_drf.tests.test_pip_helpers.
TestPipHelpers
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Test pip_helpers.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_search module¶
Test search backend.
-
class
django_elasticsearch_dsl_drf.tests.test_search.
TestSearch
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test search.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_search_multi_match module¶
Test multi match search filter backend.
-
class
django_elasticsearch_dsl_drf.tests.test_search_multi_match.
TestMultiMatchSearch
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test multi match search.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_search_simple_query_string module¶
Test multi match search filter backend.
-
class
django_elasticsearch_dsl_drf.tests.test_search_simple_query_string.
TestSimpleQueryStringSearch
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test simple query string search.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_serializers module¶
Test serializers.
-
class
django_elasticsearch_dsl_drf.tests.test_serializers.
TestSerializers
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test serializers.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_suggesters module¶
Test suggestions backend.
-
class
django_elasticsearch_dsl_drf.tests.test_suggesters.
TestContextSuggesters
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
Test context suggesters.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.test_suggesters.
TestSuggesters
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
Test suggesters.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.test_suggesters.
TestSuggestersEmptyIndex
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
Test suggesters on empty index.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_views module¶
Test views.
-
class
django_elasticsearch_dsl_drf.tests.test_views.
TestViews
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test views.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
django_elasticsearch_dsl_drf.tests.test_wrappers module¶
Test wrappers.
-
class
django_elasticsearch_dsl_drf.tests.test_wrappers.
TestWrappers
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Test wrappers.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={})]¶
-
classmethod
setUpClass
()[source]¶ Hook method for setting up class fixture before running tests in the class.
-
test_wrapper_as_json
()[source]¶ Test :Wrapper:`as_json` property.
-
Module contents¶
Tests.
-
class
django_elasticsearch_dsl_drf.tests.
TestFacetedSearch
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test faceted search.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestFilteringCommon
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
,django_elasticsearch_dsl_drf.tests.data_mixins.BooksMixin
Test filtering common.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
test_default_filter_lookup
()[source]¶ Test default filter lookup.
Example:
- http://localhost:8000/search/books-default-filter-lookup/
- ?authors=Robin&authors=Luc
-
-
class
django_elasticsearch_dsl_drf.tests.
TestFilteringGeoSpatial
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test filtering geo-spatial.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
test_field_filter_geo_bounding_box_fail_test
()[source]¶ Test field filter geo-bounding-box (fail test).
Returns:
-
test_field_filter_geo_distance
()[source]¶ Field filter geo-distance.
Example:
http://localhost:8000 /api/publisher/?location__geo_distance=1km__48.8549__2.3000Returns:
-
test_field_filter_geo_distance_distance_type_arc
()[source]¶ Field filter geo-distance.
Example:
http://localhost:8000 /api/publisher/?location__geo_distance=1km__48.8549__2.3000__arcReturns:
-
test_field_filter_geo_distance_not_enough_args_fail
()[source]¶ Field filter geo-distance. Fail test on not enough args.
Example:
http://localhost:8000 /api/publisher/?location__geo_distance=1km__48.8549Returns:
-
-
class
django_elasticsearch_dsl_drf.tests.
TestFilteringGlobalAggregations
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
,django_elasticsearch_dsl_drf.tests.data_mixins.BooksMixin
Test filtering with global aggregations.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestFilteringNested
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
Test filtering nested.
-
base_url
¶
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestFilteringPostFilter
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
,django_elasticsearch_dsl_drf.tests.data_mixins.BooksMixin
Test filtering post_filter.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestFunctionalSuggesters
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
Test functional suggesters.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestHelpers
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseTestCase
Test helpers.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestHighlight
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test highlight.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestMultiMatchSearch
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test multi match search.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestSimpleQueryStringSearch
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test simple query string search.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestOrdering
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test ordering.
-
static
deep_get
(dic, keys, default=None)[source]¶ Returns value at period separated keys in dictionary or default
From https://stackoverflow.com/a/46890853
Parameters: - dic (dict) – Dictionary to retrieve value from.
- keys (str) – Period separated path of keys
- default (str) – Default value to return if keys not found
Returns: Value at keys or default
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
test_address_order_by_nested_field_continent_ascending
()[source]¶ Order by field continent.country.name.raw ascending.
-
test_address_order_by_nested_field_continent_descending
()[source]¶ Order by field continent.country.name.raw descending.
-
test_address_order_by_nested_field_country_ascending
()[source]¶ Order by field continent.country.name.raw ascending.
-
test_address_order_by_nested_field_country_descending
()[source]¶ Order by field continent.country.name.raw descending.
Author order by default.
Order by field name ascending.
Order by field id descending.
Order by field name ascending.
Order by field name descending.
-
static
-
class
django_elasticsearch_dsl_drf.tests.
TestOrderingGeoSpatial
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test ordering geo-spatial.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
test_field_filter_geo_distance
()[source]¶ Field filter geo_distance.
Example:
http://localhost:8000 /api/publisher/?ordering=location;48.85;2.30;km;plane
-
-
class
django_elasticsearch_dsl_drf.tests.
TestPagination
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test pagination.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestPipHelpers
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Test pip_helpers.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestSearch
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test search.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestSerializers
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test serializers.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestSuggesters
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
,django_elasticsearch_dsl_drf.tests.data_mixins.AddressesMixin
Test suggesters.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestViews
(methodName='runTest')[source]¶ Bases:
django_elasticsearch_dsl_drf.tests.base.BaseRestFrameworkTestCase
Test views.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={}), Mark(name='django_db', args=(), kwargs={})]¶
-
-
class
django_elasticsearch_dsl_drf.tests.
TestWrappers
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
Test wrappers.
-
pytestmark
= [Mark(name='django_db', args=(), kwargs={})]¶
-
classmethod
setUpClass
()[source]¶ Hook method for setting up class fixture before running tests in the class.
-
test_wrapper_as_json
()[source]¶ Test :Wrapper:`as_json` property.
-
Submodules¶
django_elasticsearch_dsl_drf.analyzers module¶
Analyzers.
django_elasticsearch_dsl_drf.apps module¶
Apps.
django_elasticsearch_dsl_drf.compat module¶
Transitional compatibility module. Contains various field wrappers and helpers for painless (testing of) Elastic 2.x to Elastic 5.x transition. This module is not supposed to solve all transition issues for you. Better move to Elastic 5.x as soon as possible.
-
django_elasticsearch_dsl_drf.compat.
get_elasticsearch_version
(default=(2, 0, 0))[source]¶ Get Elasticsearch version.
Parameters: default (tuple) – Default value. Mainly added for building the docs when Elasticsearch is not running. Returns: Return type: list
-
django_elasticsearch_dsl_drf.compat.
KeywordField
(**kwargs)¶ Keyword field.
Parameters: kwargs – Returns:
-
django_elasticsearch_dsl_drf.compat.
StringField
(**kwargs)¶ String field.
Parameters: kwargs – Returns:
django_elasticsearch_dsl_drf.constants module¶
Constants module. Contains Elasticsearch constants, lookup constants, functional constants, suggesters, etc.
django_elasticsearch_dsl_drf.helpers module¶
Helpers.
-
django_elasticsearch_dsl_drf.helpers.
get_document_for_model
(model)[source]¶ Get document for model given.
Parameters: model (Subclass of django.db.models.Model.) – Model to get document index for. Returns: Document index for the given model. Return type: Subclass of django_elasticsearch_dsl.DocType.
-
django_elasticsearch_dsl_drf.helpers.
get_index_and_mapping_for_model
(model)[source]¶ Get index and mapping for model.
Parameters: model (Subclass of django.db.models.Model.) – Django model for which to get index and mapping for. Returns: Index and mapping values. Return type: tuple.
-
django_elasticsearch_dsl_drf.helpers.
more_like_this
(obj, fields, max_query_terms=25, min_term_freq=2, min_doc_freq=5, max_doc_freq=0, query=None)[source]¶ More like this.
https://www.elastic.co/guide/en/elasticsearch/reference/current/ query-dsl-mlt-query.html
Parameters: - obj (Instance of django.db.models.Model (sub-classed) model.) – Django model instance for which similar objects shall be found.
- fields (list) – Fields to search in.
- max_query_terms (int) –
- min_term_freq (int) –
- min_doc_freq (int) –
- max_doc_freq (int) –
- query (elasticsearch_dsl.query.Q) – Q query
Returns: List of objects.
Return type: elasticsearch_dsl.search.Search
Example:
>>> from django_elasticsearch_dsl_drf.helpers import more_like_this >>> from books.models import Book >>> book = Book.objects.first() >>> similar_books = more_like_this( >>> book, >>> ['title', 'description', 'summary'] >>> )
-
django_elasticsearch_dsl_drf.helpers.
sort_by_list
(unsorted_dict, sorted_keys)[source]¶ Sort an OrderedDict by list of sorted keys.
Parameters: - unsorted_dict (collections.OrderedDict) – Source dictionary.
- sorted_keys (list) – Keys to sort on.
Returns: Sorted dictionary.
Return type: collections.OrderedDict
django_elasticsearch_dsl_drf.pagination module¶
Pagination.
-
class
django_elasticsearch_dsl_drf.pagination.
LimitOffsetPagination
(*args, **kwargs)[source]¶ Bases:
rest_framework.pagination.LimitOffsetPagination
A limit/offset pagination.
Example:
-
get_count
(es_response)[source]¶ Determine an object count, supporting either querysets or regular lists.
-
-
class
django_elasticsearch_dsl_drf.pagination.
Page
(object_list, number, paginator, facets)[source]¶ Bases:
django.core.paginator.Page
Page for Elasticsearch.
-
class
django_elasticsearch_dsl_drf.pagination.
PageNumberPagination
(*args, **kwargs)[source]¶ Bases:
rest_framework.pagination.PageNumberPagination
Page number pagination.
A simple page number based style that supports page numbers as query parameters.
Example:
django_elasticsearch_dsl_drf.pip_helpers module¶
Pip helpers module.
django_elasticsearch_dsl_drf.serializers module¶
Serializers.
-
class
django_elasticsearch_dsl_drf.serializers.
DocumentSerializer
(instance=None, data=<class 'rest_framework.fields.empty'>, **kwargs)[source]¶ Bases:
rest_framework.serializers.Serializer
A dynamic DocumentSerializer class.
django_elasticsearch_dsl_drf.utils module¶
Utils.
django_elasticsearch_dsl_drf.versions module¶
Contains information about the current Elasticsearch version in use, including (LTE and GTE).
django_elasticsearch_dsl_drf.viewsets module¶
Base ViewSets.
-
class
django_elasticsearch_dsl_drf.viewsets.
BaseDocumentViewSet
(*args, **kwargs)[source]¶ Bases:
rest_framework.viewsets.ReadOnlyModelViewSet
Base document ViewSet.
-
document
= None¶
-
document_uid_field
= 'id'¶
-
ignore
= []¶
-
pagination_class
¶ alias of
django_elasticsearch_dsl_drf.pagination.PageNumberPagination
-
-
class
django_elasticsearch_dsl_drf.viewsets.
DocumentViewSet
(*args, **kwargs)[source]¶ Bases:
django_elasticsearch_dsl_drf.viewsets.BaseDocumentViewSet
,django_elasticsearch_dsl_drf.viewsets.SuggestMixin
,django_elasticsearch_dsl_drf.viewsets.FunctionalSuggestMixin
DocumentViewSet with suggest and functional-suggest mix-ins.
-
class
django_elasticsearch_dsl_drf.viewsets.
FunctionalSuggestMixin
[source]¶ Bases:
object
Functional suggest mixin.
django_elasticsearch_dsl_drf.wrappers module¶
-
django_elasticsearch_dsl_drf.wrappers.
dict_to_obj
(mapping)[source]¶ dict to obj mapping.
Parameters: mapping (dict) – Returns: Return type: Wrapper
-
django_elasticsearch_dsl_drf.wrappers.
obj_to_dict
(obj)[source]¶ Wrapper to dict.
Parameters: obj (`obj`:Wrapper:) – Returns: Return type: dict
-
class
django_elasticsearch_dsl_drf.wrappers.
Wrapper
[source]¶ Bases:
object
Wrapper.
Example: >>> from django_elasticsearch_dsl_drf.wrappers import dict_to_obj >>> >>> mapping = { >>> ‘country’: { >>> ‘name’: ‘Netherlands’, >>> ‘province’: { >>> ‘name’: ‘North Holland’, >>> ‘city’: { >>> ‘name’: ‘Amsterdam’, >>> } >>> } >>> } >>> } >>> >>> wrapper = dict_to_obj(mapping) >>> wrapper.country.name >>> “Netherlands” >>> wrapper.country.province.name >>> “North Holland” >>> wrapper.country.province.city.name >>> “Amsterdam” >>> wrapper.as_dict >>> { >>> ‘country’: { >>> ‘name’: ‘Netherlands’, >>> ‘province’: { >>> ‘name’: ‘North Holland’, >>> ‘city’: { >>> ‘name’: ‘Amsterdam’, >>> } >>> } >>> } >>> } >>> str(wrapper) >>> “Netherlands”
-
as_dict
¶ As dict.
Returns: Return type: dict
-
as_json
¶ As JSON.
Returns: Return type: str
-
Module contents¶
Integrate Elasticsearch DSL with Django REST framework.