Django SearchRank 没有考虑全文搜索运算符

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

我正在尝试添加一个新端点,该端点使用

AND, OR, NOT
运算符进行全文搜索,并且还可以容忍
TriagramSimilarity
的拼写错误。

我遇到了这个问题:在 django 1.10 中将三字母组合与排名搜索 并尝试使用这种方法,但

SearchRank
的行为并不像我预期的那样,我对它的工作原理感到困惑。

当我的代码看起来像全文搜索的基本实现时,否定过滤器工作正常

    @action(detail=False, methods=["get"])
    def search(self, request, *args, **kwargs):
        search_query = request.query_params.get("search")
        vector = SearchVector("name", weight="A")
        query = SearchQuery(search_query, search_type="websearch")

        qs = Project.objects.annotate(
            search=vector,
        ).filter(
            search=query,
        )

        return Response({
            "results": qs.values()
        })

但是我需要使用

SearchRank
来实现这个,这样我以后可以用排名分数和相似性分数做一些逻辑。

这就是我的代码看起来像注释等级而不是使用 tsvector 注释:

    @action(detail=False, methods=["get"])
    def search(self, request, *args, **kwargs):
        search_query = request.query_params.get("search")
        vector = SearchVector("name", weight="A")
        query = SearchQuery(search_query, search_type="websearch")
        rank = SearchRank(vector, query, cover_density=True)

        qs = Project.objects.annotate(
            rank=rank,
        ).order_by("-rank")
        return Response({
            "results": qs.values()
        })



响应如下:

名为“APT29 Attack Graph”的文档的排名是 1。我希望

-
运营商会将其排名较低,理想情况下为 0.

SearchRank 是否不考虑任何搜索运算符?

这是查询集的 PostgreSQL 样子

'Sort  (cost=37.78..37.93 rows=62 width=655)\n  Sort Key: (ts_rank_cd(setweight(to_tsvector(COALESCE(name, \'\'::text)), \'A\'::"char"), websearch_to_tsquery(\'apt29 -graph\'::text))) DESC\n  ->  Seq Scan on firedrill_project  (cost=0.00..35.93 rows=62 width=655)'

另外,如果有更好的方法在不引入新依赖项(Elasticsearch、haystack 等)的情况下进行这种搜索,请参考。

我尝试了不同的搜索运算符。寻找其他方法来做到这一点,到目前为止我没有成功。

python django postgresql django-rest-framework full-text-search
1个回答
1
投票

Django

SearchRank
不考虑搜索运算符,因为它只根据搜索查询与文档的匹配程度计算排名。

让我们使用

SearchQuery
根据搜索运算符过滤结果,并使用
TrigramSimilarity
计算相似度分数。

编辑:现在我们同时考虑了全文搜索和三元组相似度

from django.contrib.postgres.search import SearchQuery, SearchVector, SearchRank
from django.contrib.postgres.aggregates import StringAgg
from django.contrib.postgres.search import TrigramSimilarity
from django.db.models import F

class ProjectViewSet(viewsets.ModelViewSet):
    queryset = Project.objects.all()
    serializer_class = ProjectSerializer

    @action(detail=False, methods=["get"])
    def search(self, request, *args, **kwargs):
        search_query = request.query_params.get("search")
        vector = SearchVector("name", weight="A")
        query = SearchQuery(search_query, search_type="websearch")

        projects = Project.objects.annotate(
            rank=SearchRank(vector, query),
            similarity=TrigramSimilarity('name', search_query),
        )

        projects = projects.annotate(
            combined_score=F('rank') * F('similarity'),
        ).order_by('-combined_score')

        return Response({
            "results": projects.values()
        })
© www.soinside.com 2019 - 2024. All rights reserved.