无法使用SQLAlchemy的ilike方法和属性getter

时间:2014-11-10 23:37:13

标签: python postgresql sqlalchemy

我正在为用户名实现搜索功能。有些名称有重音字符,但我希望能够用最近的ascii字符近似值搜索它们。例如:Vû Trån可以使用Vu Tran进行搜索。

我找到了一个名为unidecode的Python库来处理这种转换。它按预期工作,并获取我的unicode字符串Vû Trån并返回Vu Tran。完美。

当我开始查询我的数据库时出现问题 - 我使用SQLAlchemy和Postgres。

这是我的Python查询:

Person.query.filter(Person.ascii_name.ilike("%{q}%".format(q=query))).limit(25).all()

ascii_name是我名字栏的获取者,以此方式实施

class Person(Base, PersonUtil):

    """
       My abbreviated Person class
    """     

     __tablename__ = 'person'

    id = Column(BigInteger, ForeignKey('user.id'), primary_key=True)
    first_name = Column(Unicode, nullable=False)
    last_name = Column(Unicode, nullable=False)

    name = column_property(first_name + " " + last_name)
    ascii_name = synonym('name', descriptor=property(fget=PersonUtil._get_ascii_name))

class PersonUtil(object):
    def _get_ascii_name(self):
        return unidecode(unicode(self.name))

我在这段代码背后的意图是,因为我在我的数据库中存储了名字和名字的unicode版本,所以当我检索这个人的名字时,我需要有办法调用unidecode(unicode(name))。因此,我使用descriptor=property(fget=...),这样每当我调用Person.ascii_name时,我都会检索“未编码的”name属性。这样,我只需编写Person.ascii_name.ilike("%{my_query}%")...并将最近的ascii_name与搜索查询匹配,搜索查询也只是ascii字符。

这不完全有效。如果查询中没有任何转换后的字符,ilike ascii_name方法可以正常工作。例如,ilike查询将用于名称“Bob Smith”,但它不适用于“BøbS​​míth”。遇到第一个转换后的角色失败,在“BøbS​​míth”的情况下是“ø”字母。

我不确定为什么会这样。 ascii_name getter返回我期望的“Bob Smith”或“Vu Tran”字符串,但当与ilike方法结合使用时,它不起作用。

  1. 为什么会这样?我一直无法找到关于这个问题的任何内容。
  2. 如何修复现有代码以使其正常工作,还是有更好的方法来实现这一点?我宁愿不必更改我的数据库架构。
  3. 谢谢。

1 个答案:

答案 0 :(得分:0)

您想要做的事情根本不起作用,因为ilike仅适用于数据库中的真实列。 column_propertysynonym只是sqlalchemy提供的语法糖,有助于简化前端。如果您想利用后端以您想要的方式使用LIKE进行查询,则需要实际值。我恐怕你必须在数据库中生成/存储ascii全名,这意味着你需要更改你的模式以包含ascii_name作为一个真正的列,并确保它们被插入。要自己验证,您应该转储表中的数据,看看手动构建的查询是否可以正常工作。