【问题标题】:Is it possible to persist a joined field in Djangos SearchVectorField?是否可以在 Django 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

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

【问题讨论】:

    标签: django postgresql full-text-search


    【解决方案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。我在这里发布了一个问题stackoverflow.com/questions/51105651/…
    • 在这里找到了你的答案! stackoverflow.com/questions/42679743/… 太棒了,谢谢
    • @nad 我为您的问题找到了有用的答案。如果它有效,请投票。
    猜你喜欢
    • 1970-01-01
    • 2017-07-29
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2022-01-24
    • 1970-01-01
    • 2011-09-20
    相关资源
    最近更新 更多