如何将Ruby函数放入SQLite3查询中?

我有一个函数,我需要将其放入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函数。 这有可能吗?

看看create_function方法 。 您可以使用它来创建这样的自定义函数(您已经定义了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连接都定义了函数 - 如果你在控制器中添加函数它似乎有效,但这并不理想)。

已经展示了如何做到这一点,我不确定它是否应该在Web应用程序中完成。 您可能不希望在生产中使用Sqlite。 也许如果你在生产中使用具有自己的levenshtein函数的Postgres(如Tin Man的回答中所建议的那样),但是想要在开发中使用Sqlite,它可能会有用。

如果需要检索列的值以将其插入Ruby函数,则必须首先检索该值。

DBM无法在您运行的代码中调用您的方法; 您必须拥有该值,将其传递给您的方法,然后在二级查询中使用该结果。

或者使用内置Levenshtein函数的DBM,如PostgreSQL或在纯SQL中定义它。