我使用sqlalchemy ORM。我有以下自定义列类型和表映射类:
class JSONEncodedDict(TypeDecorator):
impl = VARCHAR
def process_bind_param(self, value, dialect):
if value is not None:
value = json.dumps(value)
return value
def process_result_value(self, value, dialect):
if value is not None:
value = json.loads(value)
return value
Base = declarative_base()
class Task(Base):
__tablename__ = 'tasks'
id = Column(INT, primary_key=True)
description = Column(JSONEncodedDict)
created = Column(TIMESTAMP)
updated = Column(TIMESTAMP)
我想使用operator' like':
查询对象tasks = session.query(Task).filter(Task.description.like("%some pattern%")).all()
但据我所知,方法process_bind_param
也会转换like
运算符的参数。所以在sql trace中我看到了
...WHERE description LIKE '"%some pattern%"'
而不是
...WHERE description LIKE '%some pattern%'
所以没有匹配的行。
如何以我想要的方式使用LIKE
运算符执行查询?
答案 0 :(得分:3)
使用literal()
可以绕过自动类型处理(或使用type_
参数强制自己):
Task.description.like(literal("%some pattern%"))
答案 1 :(得分:1)
另一种方法是在尝试使用cast()
,type_coerce()
之类的运算符之前,先使用like
或contains
强制将该列转换为文本或其他内容:
from sqlalchemy import type_coerce, String
stmt = select([my_table]).where(
type_coerce(my_table.c.json_data, String).like('%foo%'))
或者您可以在自定义类型类定义中执行此操作:
from sqlalchemy.sql import operators
from sqlalchemy import String
class JSONEncodedDict(TypeDecorator):
impl = VARCHAR
def coerce_compared_value(self, op, value):
if op in (operators.like_op, operators.notlike_op):
return String()
else:
return self
def process_bind_param(self, value, dialect):
if value is not None:
value = json.dumps(value)
return value
def process_result_value(self, value, dialect):
if value is not None:
value = json.loads(value)
return value
ref:doc