python – 使用SQLAlchemy正确使用MySQL全文搜索
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – 使用SQLAlchemy正确使用MySQL全文搜索,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4050字,纯文字阅读大概需要6分钟。
内容图文
我希望能够在我的一个SQLAlchemy映射对象的几个文本字段中进行全文搜索.我还希望我的映射对象支持外键和事务.
我计划使用MySQL来运行全文搜索.但是,据我所知,MySQL只能在MyISAM表上运行全文搜索,而MyISAM表不支持事务和外键.
为了实现我的目标,我计划创建两个表.我的代码看起来像这样:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
description = Column(Text)
users_myisam = Table('users_myisam', Base.metadata,
Column('id', Integer),
Column('name', String(50)),
Column('description', Text),
mysql_engine='MyISAM')
conn = Base.metadata.bind.connect()
conn.execute("CREATE FULLTEXT INDEX idx_users_ftxt \
on users_myisam (name, description)")
然后,要搜索我将运行此:
q = 'monkey'
ft_search = users_myisam.select("MATCH (name,description) AGAINST ('%s')" % q)
result = ft_search.execute()
for row in result: print row
这似乎有效,但我有几个问题:
>我的方法是创建两个表来合理地解决我的问题吗?是否有标准/更好/更清洁的方法来做到这一点?
>是否有SQLAlchemy方法来创建全文索引,或者我最好直接执行“CREATE FULLTEXT INDEX …”,如上所述?
>在我的搜索/匹配查询中看起来我有一个SQL注入问题.如何选择“SQLAlchemy方式”来解决这个问题?
>是否有一种干净的方式将users_myisam选择/匹配加入到我的用户表中并返回实际的用户实例,因为这是我真正想要的?
>为了使我的users_myisam表与我的映射对象用户表保持同步,我是否有必要在我的User类上使用MapperExtension,并设置before_insert,before_update和before_delete方法来适当地更新users_myisam表,或者有没有更好的方法来实现这一目标?
谢谢,
迈克尔
解决方法:
Is my approach of creating two tables to solve my problem reasonable?
Is there a standard/better/cleaner way to do this?
我之前没有见过这个用例,因为重视事务和约束的开发人员倾向于首先使用Postgresql.我知道在您的具体情况下可能无法实现.
Is there a SQLAlchemy way to create the fulltext index, or am I best
to just directly execute “CREATE FULLTEXT INDEX …” as I did above?
conn.execute()很好但是如果你想要稍微集成一些东西你可以使用DDL()构造,请阅读http://docs.sqlalchemy.org/en/rel_0_8/core/schema.html?highlight=ddl#customizing-ddl以获取详细信息
Looks like I have a SQL injection problem in my search/match against query. How can I do the
select the “SQLAlchemy way” to fix this?
注意:此配方仅适用于同时对多个列进行MATCH – 如果您只有一列,请更简单地使用match()运算符.
最基本的你可以使用text()结构:
from sqlalchemy import text, bindparam
users_myisam.select(
text("MATCH (name,description) AGAINST (:value)",
bindparams=[bindparam('value', q)])
)
更全面地说,您可以定义自定义构造:
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import ClauseElement
from sqlalchemy import literal
class Match(ClauseElement):
def __init__(self, columns, value):
self.columns = columns
self.value = literal(value)
@compiles(Match)
def _match(element, compiler, **kw):
return "MATCH (%s) AGAINST (%s)" % (
", ".join(compiler.process(c, **kw) for c in element.columns),
compiler.process(element.value)
)
my_table.select(Match([my_table.c.a, my_table.c.b], "some value"))
文档:
http://docs.sqlalchemy.org/en/rel_0_8/core/compiler.html
Is there a clean way to join the users_myisam select/match against right back
to my user table and return actual User instances, since this is what I really want?
你可能应该创建一个UserMyISAM类,像User一样映射它,然后使用relationship()将两个类链接在一起,然后像这样的简单操作是可能的:
query(User).join(User.search_table).\
filter(Match([UserSearch.x, UserSearch.y], "some value"))
In order to keep my users_myisam table in sync with my mapped object
user table, does it make sense for me to use a MapperExtension on my
User class, and set the before_insert, before_update, and
before_delete methods to update the users_myisam table appropriately,
or is there some better way to accomplish this?
不推荐使用MapperExtensions,因此您至少使用event API,并且在大多数情况下,我们希望尝试在刷新过程之外应用对象突变.在这种情况下,我将使用User的构造函数,或者使用init event,以及一个基本的@validates装饰器,它将接收User上目标属性的值,并将这些值复制到User.search_table中.
总的来说,如果你从其他来源学习SQLAlchemy(比如Oreilly的书),它真的已经过时多年了,而且我会专注于当前的在线文档.
内容总结
以上是互联网集市为您收集整理的python – 使用SQLAlchemy正确使用MySQL全文搜索全部内容,希望文章能够帮你解决python – 使用SQLAlchemy正确使用MySQL全文搜索所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。