Select 使用 django ORM 的最长匹配子串

Select longest matching substring using django ORM

我有一个问题与 this 基本相同,只是我想尽可能使用 Django ORM 来实现它。

链接的问题说:


您将如何在 varchar 变量中搜索最长的匹配项?例如,the_table 具有如下条目:

magic_word |  prize
===================
         sh|  [=11=].20
        sha|  [=11=].40
       shaz|  [=11=].60
      shaza|  .50

我想编写一个 plpgsql 函数,它在其他参数中接受一个字符串作为输入(例如 shazam),returns 'prize' 行上的 [=] 36=] 与最长的匹配子串。在显示的示例中,.50 在 magic_word shaza 的行上。


我想在 Django 中模拟的答案是

SELECT magic_word
FROM   the_table
WHERE  'shazam' LIKE (magic_word || '%')
ORDER  BY magic_word DESC
LIMIT  1;

...但我看不到如何执行“向后”[=1​​6=] 语句。

(“向后”是指 LIKE 的 lhs 上的输入变量)

您可以implement a custom lookup,例如:

from django.db import models
from django.db.models import Field
from django.db.models import Lookup

@Field.register_lookup
class PrefixOfLookup(Lookup):
    lookup_name = 'prefix_of'

    def as_sql(self, compiler, connection):
        lhs, lhs_params = self.process_lhs(compiler, connection)
        rhs, rhs_params = self.process_rhs(compiler, connection)
        params = lhs_params + rhs_params
        return "%s LIKE (%s || '%%%%')" % (rhs, lhs), params

class Xyz(models.Model):
    @staticmethod
    def get_by_longest_match(keyword):
        qs = Xyz.objects.filter(magic_word__prefix_of=keyword).order_by('-magic_word')
        if not qs:
            return None
        else:
            return qs[0]

    magic_word = models.CharField(max_length=200)
    price = models.CharField(max_length=200)

用法示例:

# python manage.py shell
>>> from testapp.models import Xyz
>>> Xyz.objects.filter(magic_word__prefix_of='shazam').order_by('-magic_word')[0].magic_word
'shaza'
>>> Xyz.get_by_longest_match('shazam').magic_word
'shaza'