我有一个函数需要放入SQLite3查询。
我有以下方法:
def levenshtein(a, b)
case
when a.empty? then b.length
when b.empty? then a.length
else [(a[0] == b[0] ? 0 : 1) + levenshtein(a[1..-1], b[1..-1]),
1 + levenshtein(a[1..-1], b),
1 + levenshtein(a, b[1..-1])].min
end
end
我想做一个看起来像这样的查询:
@results = The_db.where('levenshtein("name", ?) < 3', '#{userinput}')
我希望在The_db
中找到name的值,其中name列的值与用户输入之间的编辑距离小于3
。问题是我不知道如何在查询中使用Ruby函数。这甚至可能吗?
答案 0 :(得分:2)
查看create_function
method。您可以使用它来创建这样的自定义函数(您已经定义了levenshtein
Ruby方法):
db.create_function "levenshtein", 2 do |func, a, b|
func.result = levenshtein(a, b)
end
然后您可以在SQL中使用它:
# first set up some data
db.execute 'create table names (name varchar(30))'
%w{Sam Ian Matt John Albert}.each do |n|
db.execute 'insert into names values (?)', n
end
#Then use the custom function
puts db.execute('select * from names where levenshtein(name, ?) < 3', 'Jan')
在此示例中,输出为
Sam
Ian
John
我没有在Rails中测试过这个,但我认为它应该可行,查询字符串只是传递给数据库。您可以使用ActiveRecord::Base.connection.raw_connection
获取Sqlite db
对象。 (我不知道如何配置Rails以便所有ActiveRecord连接都定义了函数 - 如果你在控制器中添加函数它似乎有效,但这并不理想。)
已经展示了可以的完成方式,我不确定是否应该在网络应用中完成。您可能不希望在生产中使用Sqlite。也许如果您使用例如它可能会有用Postgres在生产中有自己的levenshtein
函数(如the Tin Man’s answer中所述),但想在开发中使用Sqlite。
答案 1 :(得分:0)
如果需要检索列的值以将其插入Ruby函数,则必须首先检索该值。
DBM无法在运行的代码中调用您的方法;您必须拥有该值,将其传递给您的方法,然后在二级查询中使用该结果。
或者使用内置Levenshtein function的DBM,如PostgreSQL,或者在纯SQL中定义它。