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

are*_*eke 3 ruby sqlite methods ruby-on-rails

我有一个函数需要放入 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
Run Code Online (Sandbox Code Playgroud)

我想做一个如下所示的查询:

@results = The_db.where('levenshtein("name", ?) < 3', '#{userinput}')
Run Code Online (Sandbox Code Playgroud)

我想找到名称The_db列的值与用户输入之间的编辑距离小于的名称值3。问题是我不知道如何在查询中使用 Ruby 函数。这可能吗?

mat*_*att 5

看看create_function方法吧。您可以使用它来创建如下所示的自定义函数(您已经定义了levenshteinRuby 方法):

\n\n
db.create_function "levenshtein", 2 do |func, a, b|\n  func.result = levenshtein(a, b)\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后您可以在 SQL 中使用它:

\n\n
# first set up some data\ndb.execute \'create table names (name varchar(30))\'\n%w{Sam Ian Matt John Albert}.each do |n|\n  db.execute \'insert into names values (?)\', n\nend\n\n#Then use the custom function\nputs db.execute(\'select * from names where levenshtein(name, ?) < 3\', \'Jan\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

在这个例子中,输出是

\n\n
db.create_function "levenshtein", 2 do |func, a, b|\n  func.result = levenshtein(a, b)\nend\n
Run Code Online (Sandbox Code Playgroud)\n\n

我还没有在 Rails 中测试过这个,但我认为它应该可以工作,查询字符串只是传递到数据库。db您可以使用以下方式获取 Sqlite对象ActiveRecord::Base.connection.raw_connection。(我不知道如何配置Rails,以便所有ActiveRecord连接都定义了该函数,但是如果您在控制器中添加该函数,它似乎确实可以工作,但这不是xe2 x80\x99t 理想)。

\n\n

展示了如何完成此操作后我\xe2\x80\x99m 不确定是否应该在网络应用程序中完成。您可能不想在生产中使用 Sqlite。如果您\xe2\x80\x99在生产中使用例如Postgres及其自己的levenshtein功能(如Tin Man\xe2\x80\x99s答案中建议的那样),但想在开发中使用Sqlite,那么它可能会很有用。

\n