"""
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
"""
from rest_framework.filters import BaseFilterBackend
from ...versions import ELASTICSEARCH_LTE_6_0
from ..mixins import FilterBackendMixin
__title__ = 'django_elasticsearch_dsl_drf.filter_backends.filtering.ids'
__author__ = 'Artur Barseghyan <artur.barseghyan@gmail.com>'
__copyright__ = '2017-2020 Artur Barseghyan'
__license__ = 'GPL 2.0/LGPL 2.1'
__all__ = ('IdsFilterBackend',)
[docs]class IdsFilterBackend(BaseFilterBackend, 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]
"""
ids_query_param = 'ids'
[docs] def get_ids_query_params(self, request):
"""Get 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.ids_query_param, [])
[docs] def get_ids_values(self, request, view):
"""Get ids values for query.
: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
"""
query_params = self.get_ids_query_params(request)
_ids = []
for _id in query_params:
_values = self.split_lookup_complex_value(_id)
_ids += _values
return _ids
[docs] 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
"""
__ids = self.get_ids_values(request, view)
if __ids:
_ids = [_i for _i in __ids if _i]
_qs_kwargs = {'values': _ids}
# Prior 7.x ``type`` argument was accepted. Starting from 7.x
# it has been deprecated. As long as 6.x is supported, this
# should stay.
if ELASTICSEARCH_LTE_6_0:
_qs_kwargs.update({'type': view.mapping})
queryset = queryset.query(
'ids',
**_qs_kwargs
)
return queryset