如何在 Django 模型字段中使用 SearchRank?
Posted
技术标签:
【中文标题】如何在 Django 模型字段中使用 SearchRank?【英文标题】:How can I use SearchRank in a Django model field? 【发布时间】:2021-11-14 13:44:31 【问题描述】:我有一个模特帖子:
class Post(models.Model):
post_title = models.CharField(max_length=120)
post_subtitle = models.TextField()
post_text = models.TextField()
vector_column = SearchVectorField(null=True)
class Meta:
indexes = (GinIndex(fields=['vector_column']),)
我在数据库中创建了一个触发器来更新vector_column
值:
create function core_post_trigger() returns trigger as $$
begin
new.vector_column :=
setweight(to_tsvector('pg_catalog.english', coalesce(new.post_title, '')), 'A') ||
setweight(to_tsvector('pg_catalog.english', coalesce(new.post_subtitle, '')), 'B') ||
setweight(to_tsvector('pg_catalog.english', coalesce(new.post_text, '')), 'C');
return new;
end
$$ language plpgsql;
create trigger vector_column_trigger
before insert or update on core_post
for each row execute procedure
core_post_trigger();
我像这样搜索这个模型:
Post.objects.filter(vector_column=SearchQuery(query, config='english', search_type='websearch')
虽然我在此搜索中应用了权重,但我没有应用排名 (to_tsrank
)。我知道我可以像这样在 Django 中申请排名:
vector = SearchVector('post_title', weight='A', config='english') + SearchVector('post_subtitle', weight='B', config='english') +
SearchVector('post_text', weight='C', config='english')
query = SearchQuery(query, search_type='websearch')
Post.objects.annotate(rank=SearchRank(vector, query)).order_by('-rank')
问题是我不知道如何将SearchRank
与我的vector_column
列一起使用,因为该列有一个GinIndex。如果我使用上面创建的这个vector
变量,我就不会使用索引,那么这个搜索就会很慢。我尝试以各种方式编写此查询,但我不知道该怎么做。例如,我试过这样:
Post.objects.annotate(SearchRank(vector_column, SearchQuery('Angel', config='english'))).order_by('-rank')
但它会引发错误vector_column is not defined
。
我怎样才能实现它?
【问题讨论】:
【参考方案1】:我找到了。我需要使用 F 表达式:
Post.objects.annotate(
rank=SearchRank(F('vector_column'),
SearchQuery(query, config='english'))
).order_by('-rank'), 15
【讨论】:
以上是关于如何在 Django 模型字段中使用 SearchRank?的主要内容,如果未能解决你的问题,请参考以下文章
django如何在 search_fields和list_filter 中包含外键字段
如何在 Django 管理员中为模型字段使用自定义表单字段?