Django ORM vs.
Elasticsearch DSL by @DjangoTricks
Django ORM Elasticsearch DSL
Query definition queryset = MyModel.objects.all() search = MyModelDocument.search()
Count queryset = queryset.count() search = search.count()
Iteration for item in queryset: for item in search:
print(item.title) print(item.title)
The generated queryset.query search.to_dict()
query
Filter by single queryset = queryset.filter(my_field__icontains=value) search = search.filter('match_phrase', my_field=value)
field containing a
value
Filter by single queryset = queryset.filter(my_field__exact=value) search = search.filter('match', my_field=value)
field exactly equal # For text fields use KeywordField() in the document:
to a value my_field = fields.KeywordField()
Filter with either from django.db import models from elasticsearch_dsl.query import Q
queryset = queryset.filter( search = search.query(
of the conditions models.Q(my_field=value) | Q('match', my_field=value) |
(OR) models.Q(my_field2=value2) Q('match', my_field2=value2)
) )
Filter with all of from django.db import models from elasticsearch_dsl.query import Q
queryset = queryset.filter( search = search.query(
the conditions models.Q(my_field=value) & Q('match', my_field=value) &
(AND) models.Q(my_field2=value2) Q('match', my_field2=value2)
) )
Filter by values queryset = queryset.filter( search = search.filter(
published_at__lte=datetime.now(), 'range',
less than or equal ) published_at={'lte': datetime.now()}
to certain value )
Filter by a value queryset = queryset.filter( from elasticsearch_dsl.query import Q
category__pk=category_id, search = search.filter(
in a nested field ) 'nested',
path='category',
query=Q('match', category__pk=category_id)
)
Filter by one of queryset = queryset.filter( from django.utils.six.moves import reduce
category__pk__in=category_ids, from elasticsearch_dsl.query import Q
many values in a ) search = search.query(
related model reduce(operator.ior, [
Q(
'nested',
path='category',
query=Q('match', category__pk=category_id),
)
for category_id in category_ids
])
)
Ordering queryset = queryset.order_by('-my_field', 'my_field2') search = search.sort('-my_field', 'my_field2')
Creating query import operator import operator
from django.utils.six.moves import reduce from django.utils.six.moves import reduce
dynamically from elasticsearch_dsl.query import Q
filters = []
if value1: queries = []
filters.append(models.Q( if value1:
my_field1=value1, queries.append(Q(
)) 'match',
if value2: my_field1=value1,
filters.append(models.Q( ))
my_field2=value2, if value2:
)) queries.append(Q(
queryset = queryset.filter( 'match',
reduce(operator.iand, filters) my_field2=value2,
) ))
search = search.query(
reduce(operator.iand, queries)
)
Pagination from django.core.paginator import ( from django.core.paginator import (
Paginator, Page, EmptyPage, PageNotAnInteger Paginator, Page, EmptyPage, PageNotAnInteger
) )
from django.utils.functional import LazyObject
paginator = Paginator(queryset, paginate_by)
page_number = request.GET.get('page') class SearchResults(LazyObject):
try: def __init__(self, search_object):
page = paginator.page(page_number) self._wrapped = search_object
except PageNotAnInteger:
page = paginator.page(1) def __len__(self):
except EmptyPage: return self._wrapped.count()
page = paginator.page(paginator.num_pages)
def __getitem__(self, index):
search_results = self._wrapped[index]
if isinstance(index, slice):
search_results = list(search_results)
return search_results
search_results = SearchResults(search)
paginator = Paginator(search_results, paginate_by)
page_number = request.GET.get('page')
try:
page = paginator.page(page_number)
except PageNotAnInteger:
page = paginator.page(1)
except EmptyPage:
page = paginator.page(paginator.num_pages)
Revision 05 March 2019 More details: http://bit.ly/2H7KK2e