在 Django/PostgreSQL 搜索结果页面上突出显示搜索词

Posted

技术标签:

【中文标题】在 Django/PostgreSQL 搜索结果页面上突出显示搜索词【英文标题】:Highlight search terms on a Django/PostgreSQL search results page 【发布时间】:2018-03-05 06:16:51 【问题描述】:

如何在 Django 1.11 中使用 PostgreSQL full text search 创建一个搜索结果页面,其中突出显示搜索的字词?

【问题讨论】:

让我确保我理解您的要求。基本上,就像这里的这个屏幕一样,如果你在 Chrome 中并且你执行 cmd/ctrl + f 并搜索“ask”并得到一堆黄色突出显示的东西。您想要相同的外观,但您希望外观是列表视图? 正确。本文讨论的内容:alistapart.com/article/searchhighlight 【参考方案1】:

即使 Django 不支持 postgresql 中的 ts_headline 功能,您也可以手动将其作为 Function 应用到 QuerySet 上进行注释:


我们需要额外的函数来操作 django ORM。这是 ts_headline 的示例。 [此示例函数的 original_source 已链接here]

标题函数示例:

from django.db import models
from django.contrib.postgres.search import Value, Func


class Headline(Func):
    function = 'ts_headline'

    def __init__(self, field, query, config=None, options=None, **extra):
        expressions = [field, query]
        if config:
            expressions.insert(0, Value(config))
        if options:
            expressions.append(Value(options))
        extra.setdefault('output_field', models.TextField())
        super().__init__(*expressions, **extra)

使用上面的函数你可以在QuerySet上使用它来注解

示例模型定义

class Video(Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    title = models.CharField(max_length=128, verbose_name="Title")

在模型标题上获得突出显示的搜索结果的步骤

    过滤得到需要注解的QuerySet 使用标题功能注释 获取文档的值

过滤对象

Video.objects.filter(filter_query)

filter_query 是一个 Q() over title filter_query = Q(title__contains=term)


标题数据注释

Video.objects.filter(filter_query).annotate(title_highlight=Headline(F('title'), text_search_query))

ts_headline 直接从文档而不是从 ts_vector 中获取输入,因此我们必须传递有关它应该访问哪个字段以及应该对其执行什么 SearchQuery 的信息。

text_Search_query 是 SearchQuery 对象,其输入与 filter_query 相同 text_search_query = SearchQuery(词条)

现在在注释之后,这个查询集在所有名为 title_highlight 的对象中包含一个额外的字段,其中包含您想要的结果:

these <b>loans</b> not being repaired


从注释字段中获取值

在 QuerySet 上使用 values_list,您可以从这些带注释的字段中获取值。

最终代码:

Video.objects.filter(filter_query).annotate(title_highlight=Headline(F('title'), text_search_query)).values_from('title','title_highlight')

【讨论】:

不错。如果您想要整个字符串,而不仅仅是提取,请使用 Headline(F('title'), text_search_query, options='HighlightAll=TRUE') 很棒的内容。真的帮助了我。谢谢 这个答案不再是最新的。从 Django 3.1 开始,有一个 SearchHeadline 类,通过 from django.contrib.postgres.search import SearchHeadline.【参考方案2】:

在 Django 3.1 中,现在有一个 SearchHeadline 类,它使这项任务变得更加简单。

【讨论】:

【参考方案3】:

这个问题是关于 Django 1.11 的。事情发生了变化,因为 Django 3.1 中有一个 SearchHeadline 类。

我在 Stack Overflow 中没有注意到太多关于此的代码,因此请考虑以下内容:

    假设 models.py 包含一个 Article 模型。它有两个 TextFields ('headline'/'content') 和一个 SearchVectorField 用于内容:

    from django.contrib.postgres.search import SearchVector, SearchVectorField, SearchHeadline
    from django.db.models import F, Q
    
    class Article(models.Model):
    headline = models.TextField()
    content = models.TextField()
    content_vector = SearchVectorField(null=True)
    

    在您的控制台/终端中,以下代码将起作用:

    query = "book"
    
    Article.objects
    .annotate(v_head=SearchHeadline(F("content"), query))
    .filter(content_vector=query)
    

    上面有两个部分 - 使用SearchHeadline 注释 v_head 'column' 的注释,然后是针对“book”查询的过滤器本身。

    假设文本是“Lorem ipsum book lorem ipsum”,输出将是:

    Lorem ipsum lorem ipsum。

你可以看到other similar code on Github。

【讨论】:

以上是关于在 Django/PostgreSQL 搜索结果页面上突出显示搜索词的主要内容,如果未能解决你的问题,请参考以下文章

在 Django/PostgreSQL 搜索结果页面上突出显示搜索词

django postgreSQL 连接问题

Docker-compose实战——Django+PostgreSQL

记录 Django 网站的在线用户快照(postgresql 后端,nginx 网络服务器)

Heroku Django Postgresql 数据库管理员,超级用户在哪里?

Django Postgresql ArrayField 聚合