ElasticSearch + DRF, ограничение в 10.000, пагинация ответов
У меня есть проект на drf, с elasticsearch, он очень капризный. Всегда ловил ошибку 10.000 при желании выдать ответов больше чем 10.000, можно сменить на max_result_window
на 100.000 и даже на 200.000, но тогда возникает ошибка
RecyclerBytesStreamOutput cannot hold more than 2GB of data
В моей БД 550.000 записей, проидексированы, и работает ок, но мне нужно сделать так, что бы ответы выгружались все, которые он способен найти не используя scroll (сильно замедляет работу и выдачу результатов). Возможно тут нужно использовать search_after?
Помогите найти правильный вариант пагинации search_after
, как сделать сортировку при TextField
?
Ниже код.
documents.py
:
@registry.register_document
class ComplaintsDocument(Document):
docs_complaints = fields.TextField()
class Index:
name = 'complaints'
settings = {
'number_of_shards': 1,
'number_of_replicas': 0,
}
class Django:
model = Complaint
views.py
:
class ComplaintList(generics.ListAPIView):
# authentication_classes = [TokenAuthentication]
# permission_classes = [IsAuthenticated]
queryset = Complaint.objects.all().order_by('-date')
serializer_class = ComplaintSerializer
filter_backends = [DjangoFilterBackend]
filterset_class = ComplaintFilter
pagination_class = LimitOffsetPagination
pagination_class.default_limit = 10
pagination_class.max_limit = 25
search_fields = ['docs_complaints', 'docs_solutions', 'docs_prescriptions']
def get(self, request, *args, **kwargs):
search_after = request.query_params.get('search_after')
if search_after:
response = self.list(request, *args, **kwargs)
response['search_after'] = search_after
return response
return self.list(request, *args, **kwargs)
class ComplaintDetail(generics.RetrieveAPIView):
# authentication_classes = [TokenAuthentication]
# permission_classes = [IsAuthenticated]
queryset = Complaint.objects.all().order_by('-date')
serializer_class = ComplaintSerializer
lookup_field = 'pk'
filters.py
:
docs_complaints = filters.CharFilter(method='search_docs_complaints', label='Поиск (точное совпадение)')
docs_complaints_2 = filters.CharFilter(method='search_docs_complaints_2', label='Поиск (сходство более 70%)')
def search_docs_complaints(self, queryset, name, value):
client = Elasticsearch(timeout=60)
s = Search(using=client, index='complaints')
s = s.query('multi_match', query=value, fields=['docs_complaints'])
s = s[0:10000]
response = s.execute()
complaint_ids = [hit.meta.id for hit in response.hits]
queryset = queryset.filter(complaint_id__in=complaint_ids)
return queryset
def search_docs_complaints_2(self, queryset, name, value):
client = Elasticsearch(timeout=60)
s = Search(using=client, index='complaints')
s = s.query('multi_match', query=value, fields=['docs_complaints'], fuzziness='AUTO')
s = s[0:10000]
response = s.execute()
complaint_ids = [hit.meta.id for hit in response.hits]
queryset = queryset.filter(complaint_id__in=complaint_ids)
return queryset
Источник: Stack Overflow на русском