考虑到大约有500万个对象,我试图在Django中为我的系统创建节省时间的搜索功能。
这是我设置查询的方式:
objects_found = (Model.objects.extra(where=["CHAR_LENGTH(attribute) > 300"])).filter(attribute__trigram_similar=query)
我知道这个QuerySet尚未完全评估,而且这正是我不想要的。
例如,要完成评估设置QuerySet,请执行以下操作:
list(objects_found)
大约需要60秒。
如果我想以经典方式获取设置QuerySet的第一项,它仍然需要约60秒,因为查询是针对所有对象启动的:
objects_found[0]
但如果我使用像first()
这样的方法:
objects_found.first()
大约需要9秒,这意味着不会评估完整的QuerySet。
让我们考虑objects_found
有500个对象。如果我需要做这样的事情怎么办?
objects_found[40]
或者这个:
objects_found[:15]
以时间有效的方式?
p.s slicing确实在db级别创建了offset选项,但由于某种原因没有时间差异。
因此,代码不会搜索所有500个对象,而只会搜索40
或15
个对象。
Django QuerySet中是否有任何实现可以完成此操作?
答案 0 :(得分:1)
您可以按照limiting querysets文档
中的说明对其进行切片来限制查询objects_found = (Model.objects.extra(where=["CHAR_LENGTH(attribute) > 300"])).filter(attribute__trigram_similar=query)[:15]
您的查询在数据库上非常困难,像CHAR_LENGTH这样的函数不是运行每个查询运行时的最佳选择,因此您可能可以将长度提取到整数行而不是执行CHAR_LENGTH。
关于trigram你可以创建索引 https://www.postgresql.org/docs/9.1/static/pgtrgm.html#AEN143603
此外,如果您更喜欢通过Django创建索引,那么以下资源可能很有用 https://vxlabs.com/2018/01/31/creating-a-django-migration-for-a-gist-gin-index-with-a-special-index-operator/