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_dbname列の値とユーザー入力の間の編集距離が。未満の場合にnameの値を見つけたいもの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 でテストしていませんが、うまくいくと思います。クエリ文字列がデータベースに渡されるだけです。を使用して Sqlitedbオブジェクトを取得できますActiveRecord::Base.connection.raw_connection。(ただし、すべての ActiveRecord 接続に関数が定義されるように Rails を構成する方法はわかりません。コントローラーに関数を追加すると機能するように見えますが、それは理想的ではありません)。

これを行う方法を示しましたが、Web アプリで行う必要があるかどうかはわかりません。おそらく本番環境で Sqlite を使用したくないでしょう。おそらく、本番環境で独自のlevenshtein機能を備えた Postgres を使用しているが ( Tin Man の回答で示唆されているように)、開発で Sqlite を使用したい場合に役立つ可能性があります。

于 2012-12-18T21:39:52.003 に答える
0

列の値を取得して Ruby 関数に挿入する必要がある場合は、まずその値を取得する必要があります。

DBM は、実行中のコードでメソッドを呼び出すことができません。値を取得してメソッドに渡し、その結果をセカンダリ クエリで使用する必要があります。

または、PostgreSQL などのレーベンシュタイン関数が組み込まれた DBM を使用するか、純粋な SQL で定義します。

于 2012-12-18T18:58:23.177 に答える