【问题标题】:How to use Substr with an F Expression如何将 Substr 与 F 表达式一起使用
【发布时间】:2022-01-20 22:14:07
【问题描述】:

我正在尝试构建一个基于 fuzzystrmatch postgres 扩展的 Func 类工具包。

例如,我有这个包装器,它接受一个表达式和一个搜索词并返回 levenshtein 距离:

class Levenshtein(Func):
    """This function calculates the Levenshtein distance between two strings:"""
    template = "%(function)s(%(expressions)s, '%(search_term)s')"
    function = "levenshtein"

    def __init__(self, expression, search_term, **extras):
        super(Levenshtein, self).__init__(
            expression,
            search_term=search_term,
            **extras
        ) 

这样调用,使用F Expression:

Author.objects.annotate(lev_dist=Levenshtein(F('name'),'JRR Tolkien').filter(lev_dist__lte=2)

但是,如果这里的 'name' 字段大于 255,则会引发错误:

源和目标都可以是任何非空字符串,最多 255 个字符。

当我使用 Substr 进行注释时,我可以截断名称:

Author.objects.annotate(clipped_name=Substr(F('name'),1,250))

但我似乎无法弄清楚如何将该逻辑放入 func 中,我将其放入 ExpressionWrapper 并按照 the docs 设置 output_field

class Levenshtein(Func):
    """This function calculates the Levenshtein distance between two strings:"""
    template = "%(function)s(%(expressions)s, '%(search_term)s')"
    function = "levenshtein"

    def __init__(self, expression, search_term, **extras):
        super(Levenshtein, self).__init__(
            expression=ExpressionWrapper(Substr(expression, 1, 250), output_field=TextField()),
            search_term=search_term,
            **extras
        ) 

【问题讨论】:

    标签: python sql django postgresql fuzzy-search


    【解决方案1】:

    虽然文档并没有说得非常清楚,但通过实验发现答案是删除expression 的额外定义并直接将ExpressionWrapper 作为第一个参数传入:

    class Levenshtein(Func):
        """This function calculates the Levenshtein distance between two strings:"""
        template = "%(function)s(%(expressions)s, '%(search_term)s')"
        function = "levenshtein"
    
        def __init__(self, expression, search_term, **extras):
            super(Levenshtein, self).__init__(
                ExpressionWrapper(Substr(expression, 1, 250), output_field=TextField()),
                search_term=search_term,
                **extras
            ) 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多