Django的。如何返回QuerySet order_by模糊模糊方法的结果?

时间:2017-07-05 13:56:14

标签: python django django-views fuzzywuzzy

这是我的模特:

class Item(models.Model):
    status = models.IntegerField(choices=STATUS_CHOICES, default=3)
    def __str__(self):
        return 'Item: {0}'.format(self.id)


class Name(models.Model):
    name = models.CharField(, max_length=600, default='')
    item = models.ForeignKey(Item, db_index=True, blank=True, null=True)
    main = models.BooleanField(default=False)

    def __str__(self):
        return '{}'.format(self.name)

我想查询set Items,因此返回按Fuzzy wuzzy.排序的X项 基本上,我需要找到匹配的项目并合并它们。

我试图创建一个字典,但速度非常慢。我有大约8万件物品,而且还在计算中。

我尝试了类似的事情:

items = Item.objects.filter(status=3)
                 .annotate( score=fuzz.ratio(query,i.name_set.all().first().name))
                 .order_by('-score')

有人能就这个话题给我一些启示吗? 感谢

2 个答案:

答案 0 :(得分:3)

如果数据库中有80.000个条目,您必须考虑以下选项:

(A)让数据库排序(最好使用一些预先创建的索引)并仅返回所选行。这允许通过数据库进行分页。

(B)尽可能快地从DB返回所有内容,并将所有80.000分类到RAM中。如果你想坚持python模块FuzzyWuzzy你必须这样做。但正如你现在所经历的那样,这可能并不快。你必须自己做分页。

  

[FuzzyWuzzy]使用Levenshtein Distance计算一个简单易用的包中序列之间的差异。

如果你使用PostgreSQL作为后端,你可以使用levenshtein函数,如下所述:

https://www.postgresql.org/docs/9.1/static/fuzzystrmatch.html

似乎有助于Django整合这个: https://github.com/django/django/pull/4825

TrigramSimilarity已经可用。您可以查看源代码并根据postgres levenshtein实现类似的东西。但我建议先试一试。它可能已经满足您的需求。

编辑:

通常,对于此大小及更多的表,请确保您的数据库具有所需的索引并使用它们。例如:Django __icontains不涵盖Django的db_index过滤器。您必须自己在该列上添加一个三元组索引。

可能是您当前的代码需要这么长时间,因为查询已经花费了不必要的时间。

答案 1 :(得分:0)

如果您使用的是 PostgreSQL ,则可以使用Trigram Similar

trigram_similar查找允许您使用专用的 PostgreSQL 扩展名执行Trigram查找,测量共享的Trigram(三个连续字符)的数量。

安装:

更新您的settings.py ::

INSTALLED_APPS = [
    ...
    'django.contrib.postgres',
]

添加新的迁移::

python manage.py makemigrations --empty yourappname

将创建一个新的迁移文件,例如:migrations/0002_auto_<date>_<time>.py。更新它::

from django.db import migrations
from django.contrib.postgres.operations import TrigramExtension
class Migration(migrations.Migration):        

    dependencies = [
        ...
    ]
    operations = [
        TrigramExtension(),
    ]

现在迁移:

./manage.py migrate

现在您可以在trigram_similarCharField上使用TextField查找,例如:

>>> City.objects.filter(name__trigram_similar="Middlesborough")
['<City: Middlesbrough>']