Новая функция TrigramS Similarity в django.contrib.postgres отлично подошла для моей проблемы. Я использую его для панели поиска, чтобы найти трудно произносимые латинские имена. Проблема в том, что существует более 2 миллионов имен, и поиск занимает больше времени, чем я хочу.
Я хотел бы создать индекс для триграмм, как описано в документации postgres https://www.postgresql.org/docs/9.6/static/pgtrgm.html
Но я не уверен, как это сделать так, чтобы API Django использовал его. Для текстового поиска postgres есть описание того, как создать индекс, но не сходство триграмм. https://docs.djangoproject.com/en/1.11/ref/contrib/postgres/search/#performance
Это то, что у меня сейчас есть:
class NCBI_names(models.Model):
tax_id = models.ForeignKey(NCBI_nodes, on_delete=models.CASCADE, default = 0)
name_txt = models.CharField(max_length=255, default = '')
name_class = models.CharField(max_length=32, db_index=True, default = '')
class Meta:
indexes = [GinIndex(fields=['name_txt'])]
В представлении get_queryset
метод:
class TaxonSearchListView(ListView):
#form_class=TaxonSearchForm
template_name='collectie/taxon_list.html'
paginate_by=20
model=NCBI_names
context_object_name = 'taxon_list'
def dispatch(self, request, *args, **kwargs):
query = request.GET.get('q')
if query:
try:
tax_id = self.model.objects.get(name_txt__iexact=query).tax_id.tax_id
return redirect('collectie:taxon_detail', tax_id)
except (self.model.DoesNotExist, self.model.MultipleObjectsReturned) as e:
return super(TaxonSearchListView, self).dispatch(request, *args, **kwargs)
else:
return super(TaxonSearchListView, self).dispatch(request, *args, **kwargs)
def get_queryset(self):
result = super(TaxonSearchListView, self).get_queryset()
#
query = self.request.GET.get('q')
if query:
result = result.exclude(name_txt__icontains = 'sp.')
result = result.annotate(similarity=TrigramSimilarity('name_txt', query)).filter(similarity__gt=0.3).order_by('-similarity')
return result