是否可以在 Django 的 SearchVectorField 中保留连接字段?

问题描述 投票:0回答:1

是否可以使用 Django 的 SearchVectorField 保留连接字段以进行全文搜索?

例如:

class P(models.Model):
    brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
    search_vector = SearchVectorField(null=True, blank=True)

代码:

p = P.objects.get(id=1)
p.search_vector = SearchVector('brand__name')
p.save()

引发此异常:

FieldError: Joined field references are not permitted in this query

如果这是不可能的,如何提高连接注释查询的性能?

django postgresql full-text-search
1个回答
7
投票

我找到了解决您问题的方法:

p = P.objects.annotate(brand_name=SearchVector('brand__name')).get(id=1)
p.search_vector = p.brand_name
p.save()

更新2023-11-23

如官方文档中所述:

如果您只是更新记录,不需要对模型对象执行任何操作,最有效的方法是调用 update(),而不是将模型对象加载到内存中。

使用 update() 还可以防止竞争条件,即在加载对象和调用 save() 之间的短时间内数据库中的某些内容可能会发生变化。

最后,意识到 update() 在 SQL 级别进行更新,因此不会在模型上调用任何 save() 方法,也不会发出 pre_save 或 post_save 信号(这是调用 Model.save 的结果) ()).

因此,在这种情况下,您可以使用此查询对数据库执行单个 SQL 查询:

from django.contrib.postgres.search import SearchVector
from django.db.models import F

P.objects.annotate(
    brand_name=SearchVector('brand__name')
).filter(
    id=1
).update(
    search_vector=F('brand_name')
)

或者更短的形式(由@christophe31建议)是:

from django.contrib.postgres.search import SearchVector

P.objects.filter(id=1).update(search_vector=SearchVector('brand__name))

以上两种解决方案都会在数据库中生成相同的 SQL 代码。

© www.soinside.com 2019 - 2024. All rights reserved.