16

開発には SQLite3 を使用し、展開には PostgreSQL を使用しています。ただし、次の問題に直面しています。

を使用した私の簡単な検索SQLite3

def self.search(search)
    if search
      find(:all, :conditions => ["style LIKE ? OR construction LIKE ?", "%#{search}%", "%#{search}%"])
    else
      find(:all)
    end
end

ただし、 では機能しません。問題を解決するには、をPostgreSQL置き換える必要があります。LIKEILIKE

def self.search(search)
    if search
      find(:all, :conditions => ["style ILIKE ? OR construction ILIKE ?", "%#{search}%", "%#{search}%"])
    else
      find(:all)
    end
end

データベース全体でこれらの検索を行う「Ruby の方法」はありますか?

編集- あなたの答えに基づいて、そのための一般的なRubyソリューションが見つかるとは思いません。

Ruby on Rails チュートリアル: Learn Rails by Example - by Michael Hartlに従いました。最終的なGemfileには両方のデータベースが表示されます...まあ、残念です...

4

7 に答える 7

50

問題の根本はここにあります:

開発にはSQLite3を使用し、展開にはPostgreSQLを使用しています。

それは悪い考えです™。あなたは非互換性にぶつかり続けるでしょう-あるいはもっと悪いことに:ダメージが与えられるまでいくつかを実現しないでください。
開発と本番環境に同じRDBMS(PostgreSQL)を使用して、無意味なトラブルを回避してください。


不幸な設定で立ち往生している間、簡単な修正があります:

lower(style) LIKE lower(?)

両方のプラットフォームで同様に機能します。

  • lower()小文字の検索パターンを指定すると、右側を削除できます。

  • 標準のSQLitelower(X)では、ASCII文字のみを折りたたむ。詳細については、SQLiteマニュアルのコア関数の章を引用します。

    lower(X)関数は、すべてのASCII文字が小文字に変換された文字列Xのコピーを返します。デフォルトの組み込みlower()関数は、ASCII文字に対してのみ機能します。非ASCII文字で大文字と小文字を変換するには、ICU拡張機能をロードします

    強調鉱山。

  • PostgreSQLlower(X)はそのままUTF-8で動作します。


歓迎すべき副作用として、式のインデックスを使用してPostgreSQLでクエリを高速化できます。これは、の基本インデックスを使用するよりも高速です。 lower(style)ILIKEstyle

pg_trgmまた、PostgreSQL 9.1以降、拡張機能を備えたGINまたはGISTインデックスを使用して、任意 LIKEのクエリを高速化できILIKEます。トリグラムでは大文字と小文字が区別されません。この関連する回答の詳細な手順とリンク:

于 2012-07-01T01:29:01.833 に答える
9

この問題を解決するには、Arel が最適な方法だと思います。Rails でアクティブ レコードに使用され、データベースに依存しません。あなたのコードは、状況に合うと思われる sqlite3 または postgres でも​​同じように機能します。一致メソッドを使用すると、postgres 環境で ilike に自動的に切り替わります。例:

users=User.arel_table
User.where(users[:style].matches("%#{search}%").or(users[:construction].matches("%#{search}%")))

github から詳細情報を取得できます: https://github.com/rails/arel/

于 2012-07-04T05:41:46.073 に答える
4

いいえ、データベースを検索する「Ruby の方法」はありません。Ruby on Rails (具体的にはActiveRecord ) には、ActiveRecord でサポートされている RDB で CRUD 操作を実行するためのヘルパー メソッドが含まれていますが、例よりも LIKE を使用して検索する方法に勝るものはありません。あなたが提供しました。

この議論に関連する Rails ドキュメントのセクションは、ActiveRecord::FinderMethodsになります。

補足として、実行する代わりにallfind(:all)を実行できます。

Rails のドキュメントでは、LIKE ステートメントを実行するために使用するのと同じ構文を使用します。つまり、次のようになります。

Person.exists?(['name LIKE ?', "%#{query}%"])

上記の方法を使用することは完全に安全です。

以下のようなステートメントが安全でない理由は、where文字列がサニタイズなしでデータベース クエリに直接渡されるためです。これにより、データベースが悪用される可能性があります (つまり、単純なアポストロフィがparams[:first_name]クエリ全体を台無しにし、データベースを脆弱なままにする可能性があります。 - 具体的には SQL インジェクション)。上記の例では、ActiveRecord はクエリに渡すパラメーターをサニタイズできます。

Client.where("first_name LIKE '%#{params[:first_name]}%'")
于 2012-06-30T20:03:59.127 に答える
2

本番環境と開発環境で異なるデータベースを使用することは良い習慣ではありませんが、それでもsqueelgemを使用することは良いケースです:https ://github.com/ernie/squeel/

これを使用すると、生のSQLよりも簡単で間違いなくはるかにクリーンで読みやすいDSLを使用してクエリを記述でき、gemは使用されるRDBMSに固有のSQLへの変換を処理します。

ライアンベイツはそれについての良いビデオを持っています:http://railscasts.com/episodes/354-squeel

于 2012-06-30T23:26:05.193 に答える
2

私はかつて同じ問題に直面していましたが、これが私の解決策です:

各データベースで関数を使用できるようにする小さな lib を作成しました。

class AdapterSpecific

  class << self
    def like_case_insensitive
      case ActiveRecord::Base.connection.adapter_name
      when 'PostgreSQL'
        'ILIKE'
      else
        'LIKE'
      end
    end    

    def random
      #something
    end
  end

モデルで使用するには:

def self.search(search)
    if search
      find(:all, :conditions => ["style #{AdapterSpecific.like_case_insensitive} :query OR construction #{AdapterSpecific.like_case_insensitive} :query", {:query => "%#{search}%"}])
    else
      find(:all)
    end
end

書いて以来、配置データベースをPostgresに移行しました。これは、いくつかの理由ではるかに優れたセットアップであるためです(他の回答を参照)。

Postgres の全文検索を使用すると、テキスト検索がより効率的になります。基本的な実装についてはtexticleを参照してください。さらにカスタマイズが必要な場合はpg_searchを参照してください。

于 2012-07-02T22:10:57.467 に答える
2

残念ながら、これに対する良い解決策を見つけることはできないと思います。:conditions の代わりに使用できる唯一の他の構文は、.where 句を使用することです。

where(["style ILIKE ? OR construction ILIKE ?", "%#{search}%", "%#{search}%"])

残念ながら、お気づきかもしれませんが、この別の構文でもまったく同じ問題が発生します。これは、実稼働環境とは大幅に異なる開発環境を使用する際に遭遇する煩わしさの 1 つにすぎません。SQLite と PostgresSQL の間には他にもかなり大きな違いがあります。Postgres を開発マシンにインストールして使用することをお勧めします。開発がずっと簡単になり、コードがずっときれいになります。

于 2012-06-28T16:42:55.357 に答える
1

を使用した検索LIKEは、データベース上で苦痛を伴う場合があります。確かに、コストが非常に高くなる可能性のあるインデックスは使用しません。

より長い答え: 開発で Postgres を使用し (sqlite3 を捨てる)、 Postgres の型style, constructionを介してすべての検索可能なフィールドにフルテキスト インデックスを作成することをお勧めします。tsvector

インデックスを使用する場合の Postgres での全文検索は非常に高速です。

于 2012-07-01T01:03:41.883 に答える