【问题标题】:Django Postgres Full Text TrigramSimilarity Multiple FieldsDjango Postgres 全文 TrigramSimilarity 多个字段
【发布时间】:2017-10-15 21:41:48
【问题描述】:

我正在尝试弄清楚如何将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)?

谢谢

【问题讨论】:

    标签: django postgresql full-text-search


    【解决方案1】:

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

    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
    

    【讨论】:

    • 不起作用..我得到一个'TrigramSimilarity' object has no attribute 'split'
    • @psychok7 我删除了 F 调用。你能再试一次吗?
    • 它似乎工作,但我对性能仍然不是很满意..您对如何优化此查询有任何想法吗? (我已经有了索引)
    • 我在文档 "unaccent lookups should perform fine in most use cases. However, queries using this filter will generally perform full table scans, which can be slow on large tables. In those cases, using dedicated full text indexing tools might be appropriate." 上找到了这个。所以如果性能在这里成为一个真正的问题,也许我应该避免使用unaccent
    • 很抱歉听到这个消息。我可以建议您的另一件事是在每个模型中都有一个包含非重音字符串的字段。你可以通过重写 save 方法来做到这一点,你可以使用 unidecode 来删除重音符号。然后,您将在“未重音”字段中进行查找。希望对您有所帮助。
    猜你喜欢
    • 2015-10-06
    • 2015-08-20
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 2011-02-05
    • 1970-01-01
    相关资源
    最近更新 更多