Django Postgres全文TrigramSimilarity多个字段

时间:2017-05-16 17:13:24

标签: django postgresql full-text-search

我正在尝试弄清楚如何将TrigramSimilarityunaccent用于多个字段。

到目前为止,我有:

def filter_by_location(self, queryset, location):
    log.info('Filtering location: "{location}"'.format(**locals()))
    queryset = queryset.filter(
        Q(accommodation__district__name__unaccent__trigram_similar=location) |
        Q(accommodation__municipality__name__unaccent__trigram_similar=location) |
        Q(accommodation__settlement__name__unaccent__trigram_similar=location)
    )

但是我在documentation中读到了我可以通过similarity订购(不确定上面的代码是否自动执行),所以我试着这样做:

    queryset = queryset.filter(
        Q(accommodation__district__name__unaccent__trigram_similar=location) |
        Q(accommodation__municipality__name__unaccent__trigram_similar=location) |
        Q(accommodation__settlement__name__unaccent__trigram_similar=location)
    ).annotate(
        similarity=TrigramSimilarity(
            'accommodation__district__name', location
        ) + TrigramSimilarity(
            'accommodation__municipality__name', location
        ) + TrigramSimilarity(
            'accommodation__settlement__name', location
        ),
    ).filter(similarity__gt=0.3).order_by('-similarity')

我很快意识到+中的TrigramSimilarity没有OR,但我需要对所有这些不同的字段进行全文搜索。

我实现这一目的的正确语法是什么(使用OR代替和AND)将查询性能考虑在内?

由于

1 个答案:

答案 0 :(得分:2)

我认为下面的代码可能会有所帮助,但我没有运行它:

queryset = queryset.annotate(
    similarity = Greatest(
        TrigramSimilarity('accommodation__district__name', location),
        TrigramSimilarity('accommodation__municipality__name', location),
        TrigramSimilarity('accommodation__settlement__name', location))
).filter(
    Q(accommodation__district__name__unaccent__trigram_similar=location) |
    Q(accommodation__municipality__name__unaccent__trigram_similar=location) |
    Q(accommodation__settlement__name__unaccent__trigram_similar=location),
  similarity__gt=0.3).order_by('-similarity')

Greatest可以像下面这样导入:

from django.db.models.functions import Greatest