【问题标题】:Poor Performance when trigram similarity and full-text-search were combined with Q ind django using postgres使用 postgres 将 trigram 相似性和全文搜索与 Q ind django 结合时性能不佳
【发布时间】:2019-06-11 07:16:55
【问题描述】:

我正在创建一个 Web 应用程序来搜索具有教育、经验等属性的人。我不能对所有字段使用全文搜索,因为有些必须是模糊匹配。 (例如:如果我们搜索 biotech,它应该选择 bio tech、biotech 和 bio-tech)。我的数据库中有大约 200 个配置文件模型条目,这些条目将出现在搜索结果中。

教育和经验等其他模型通过外键连接到个人资料

因此,我决定选择在什么领域使用什么方法。对于学位名称(在教育模型中)等较短的字段,我想使用三元相似度。对于教育描述等领域,我使用全文搜索。

但是,由于我必须在多个字段中执行此操作,因此我使用了简单的查找而不是使用搜索向量。

Profile.objects.filter(
    Q(first_name__trigram_similar=search_term) |
    Q(last_name__trigram_similar=search_term) |
    Q(vision_expertise__search=search_term) |
    Q(educations__degree__trigram_similar=search_term) |
    Q(educations__field_of_study__trigram_similar=search_term) |
    Q(educations__school__trigram_similar=search_term) |
    Q(educations__description__search=search_term) |
    Q(experiences__title__trigram_similar=search_term) |
    Q(experiences__company__trigram_similar=search_term) |
    Q(experiences__description__search=search_term) |
    Q(publications__title__trigram_similar=search_term) |
    Q(publications__description__search=search_term) |
    Q(certification__certification_name__trigram_similar=search_term) |
    Q(certification__certification_authority__trigram_similar=search_term) |
    Q(bio_description__search=search_term) |
)

每次搜索我都会得到预期的结果。但是,获得它所需的时间非常缓慢。我不知道如何让它更快。

【问题讨论】:

    标签: python django postgresql full-text-search trigram


    【解决方案1】:

    没有类代码,很难找到优化查询的更好方法。

    您可以添加GinGist 索引来加快三元相似度。

    您可以使用SearchVector 构建注释,如下所示:

    from django.contrib.postgres.aggregates import StringAgg
    from django.contrib.postgres.search import SearchQuery, SearchVector
    
    search_vectors = (
        SearchVector('vision_expertise') +
        SearchVector('bio_description') +
        SearchVector(StringAgg('experiences__description', delimiter=' ')) +
        SearchVector(StringAgg('educations__description', delimiter=' ')) +
        SearchVector(StringAgg('publications__description', delimiter=' '))
    )
    
    Profile.objects.annotate(
        search=search_vectors
    ).filter(
        Q(search=SearchQuery(search_term)) |
        Q(first_name__trigram_similar=search_term) |
        Q(last_name__trigram_similar=search_term) |
        Q(educations__degree__trigram_similar=search_term) |
        Q(educations__field_of_study__trigram_similar=search_term) |
        Q(educations__school__trigram_similar=search_term) |
        Q(experiences__title__trigram_similar=search_term) |
        Q(experiences__company__trigram_similar=search_term) |
        Q(publications__title__trigram_similar=search_term) |
        Q(certification__certification_name__trigram_similar=search_term) |
        Q(certification__certification_authority__trigram_similar=search_term)
    )
    

    您可以使用SearchVectorField 加速全文搜索

    要了解全文搜索和三元组,您可以阅读我写的关于该主题的文章:

    "Full-Text Search in Django with PostgreSQL"

    【讨论】:

    • 感谢您的回答。我正在尝试实现一个 SearchVectorField。我实际上给出了您刚刚在答案中给出的搜索向量。但是,我收到一条错误消息 FieldError: Joined field references are not permitted in this query
    • 我认为我们不能在这个领域使用聚合器,比如StringAgg。有解决办法吗?
    • 正如我之前所说,如果没有课程代码,我不可能给出完整的答案。
    【解决方案2】:

    在 postgres 中添加 Trigram 索引以提高性能,即用于 users.first_name 和 users.last_name 索引:

    CREATE INDEX index_users_full_name
                 ON users using gin ((first_name || ' ' || last_name) gin_trgm_ops);
    

    【讨论】:

      猜你喜欢
      • 2016-10-18
      • 2018-02-03
      • 1970-01-01
      • 2012-12-29
      • 2015-09-08
      • 1970-01-01
      • 1970-01-01
      • 2014-02-18
      相关资源
      最近更新 更多