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

Posted

技术标签:

【中文标题】是否可以在 Django SearchVectorField 中保留一个连接字段?【英文标题】:Is it possible to persist a joined field in Djangos SearchVectorField? 【发布时间】:2018-02-02 11:09:38 【问题描述】:

是否可以使用 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

如果这是不可能的,您如何提高联合注释查询的性能?

【问题讨论】:

【参考方案1】:

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

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

2018 年 6 月 29 日更新

据官方documentation报道:

如果您只是更新一条记录并且不需要对模型对象做任何事情,最有效的方法是调用 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')
)

【讨论】:

你不是用那个.get(id=1) 做一个冗余的数据库查询吗?我也在寻找一种解决方案,从外来关系构建搜索向量。 @Nad 我已经用仅在 db 上执行一个查询的解决方案更新了我的答案,但请阅读有关保存和更新之间区别的文档 感谢您。我的问题是我已经有一个模型实例,并且我想从 post_save 信号更新 search_vector。我在这里发布了一个问题***.com/questions/51105651/… 在这里找到了你的答案! ***.com/questions/42679743/… 太棒了,谢谢 @nad 我为您的问题找到了有用的答案。如果它有效,请投票。

以上是关于是否可以在 Django SearchVectorField 中保留一个连接字段?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Django 中基于全文搜索功能 SearchRank 创建自定义排名?

是否可以在 django rest 框架序列化程序中使用重用 django 表单进行验证?

是否有任何工具可以自动在Django中为模型创建模板

是否可以在 django 模型上覆盖 .objects?

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

是否可以在 Django 上使用 Python SpeechRecognition?