姜戈。如何return QuerySet order_by 一个模糊wuzzy方法的结果?

Django. How to return QuerySet order_by result of a fuzzy wuzzy method?

这是我的模型:

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)

我想查询集合项目,所以 returns X 项目按 Fuzzy wuzzy. 排序 基本上,我需要找到匹配的项目并合并它们。

我尝试创建字典,但速度非常慢。我有大约 80 000 件商品,而且还在增加中。

我试过类似的东西:

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

谁能给我一些关于这个话题的信息? 谢谢

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

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

(B) return 尽可能快地从数据库中获取所有内容,并在 RAM 中对所有 80.000 进行排序。如果你想坚持使用 python 模块 FuzzyWuzzy,你将不得不这样做。但正如您现在所经历的那样,这可能不会很快。您必须自己进行分页。

[FuzzyWuzzy] uses Levenshtein Distance to calculate the differences between sequences in a simple-to-use package.

如果您使用 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 覆盖。您必须自己在该列上添加一个三元组索引。

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

如果您正在使用 PostgreSQL,您可以使用 Trigram Similar

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

安装:

更新您的 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_similar 查找 CharFieldTextField 例如:

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