这是我的模特:
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')
有人能就这个话题给我一些启示吗? 感谢
答案 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_similar
和CharField
上使用TextField
查找,例如:
>>> City.objects.filter(name__trigram_similar="Middlesborough")
['<City: Middlesbrough>']