2

我有一个需要放入 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在名称列的值与用户输入之间的编辑距离小于的地方找到名称的值3。问题是我不知道如何在查询中使用 Ruby 函数。这甚至可能吗?

4

2 回答 2

4

看看create_function方法。您可以使用它来创建这样的自定义函数(您已经定义了levenshteinRuby 方法):

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 中测试过,但我认为它应该可以工作,查询字符串只是传递到数据库。您可以db使用ActiveRecord::Base.connection.raw_connection. (我不知道如何配置 Rails,以便所有 ActiveRecord 连接都定义了函数——如果你在控制器中添加函数,它似乎确实有效,但这并不理想)。

展示了如何做到这一点后,我不确定是否应该在网络应用程序中完成。您可能不想在生产中使用 Sqlite。levenshtein如果您在生产中使用例如具有自己功能的 Postgres(如Tin Man 的回答中所建议的那样),但想在开发中使用 Sqlite,它可能会很有用。

于 2012-12-18T21:39:52.003 回答
0

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

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

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

于 2012-12-18T18:58:23.177 回答