RailsのDBクエリメソッドをより効率的にする方法

Ilja KO

POSTGRESQLDBに対してクエリを実行しています。私のアプリには記事があり、記事にはいくつかのハッシュタグを付けることができます。これらの関係は、ハッシュタグと記事の結合されたテーブルに保存されます。

特定のハッシュタグを含む記事を返す、または特定のハッシュタグを含まないすべての記事を返す作業方法があります

  def test(hashtags, include = true)
    articles= []
    hashtags.split(' ').each do |h|
      articles+= Article.joins(:hashtags).where('LOWER(hashtags.value) LIKE LOWER(?)', "#{h}")
    end
    if include
      articles.uniq
    else 
      (Article.all.to_set - articles.uniq.to_set).to_a
    end
  end

私はそれをこのように呼ぶことができます:

test("politics people china", true)

そしてそれは私にそれらのハッシュタグの1つを持っているすべての記事を与えるでしょう

または私はそれをそのように呼ぶことができます

test("politics people china", false)

そしてそれは私にこれらのハッシュタグの1つを持っている人を除いてすべての記事を与えるでしょう

それはうまく機能しますが、DBレベルではなくRubyで多くのことを行うので、これはあまり効率的ではないと思います。

私はこれを試しました:

def test2(hashtags, include = true)
    articles= []
    pattern = ''
    hashtags.split(' ').each do |h|
      pattern += "#{h}|"
    end
    pattern = '(' + pattern[0...-1] + ')'

    if include
      articles = Article.joins(:hashtags).where('hashtags.value ~* ?', "#{pattern}")
    else 
      articles = Article.joins(:hashtags).where('hashtags.value !~* ?', "#{pattern}")
    end

    articles.uniq
  end

しかし、思ったようには動作しません。まず第一に、私がそれをそのように呼ぶならば:

test2("politics china", true)

ハッシュタグpoliticsまたはを持っているすべての記事だけでなく、次のようなchina文字の1つを含むハッシュタグを持っているすべての記事も表示されますpoliticschina

(p|o|l|i|t|c|s|h|n|a)

しかし、実際にこれをチェックする必要があり、パターンは実際には次のようになります。コンソールに表示されます。

(politics|china)

私が見つけたものは奇妙なtbhではありません...

そしてと

test2("politics", false)

1つ以上のハッシュタグが関連付けられている記事のみが表示されますが、ハッシュタグがまったくない記事は除外されます

誰かが私の作業方法をより効率的にするのを手伝ってもらえますか?

編集:これは答えで提案されたような私の更新されたコードです

def test2(hashtags, include = false)    
    hashtags = 
    if include 
      Hashtag.where("LOWER(value) iLIKE ANY ( array[?] )", hashtags)
    else
      Hashtag.where("LOWER(value) NOT iLIKE ANY ( array[?] )", hashtags)
    end
    Slot.joins(:hashtags).merge(hashtags).distinct
  end

incude残念ながら偽の場合、ハッシュタグがまったくない記事を私に与えることはまだ不足しています

イリヤ・コニュホフ

あなたは正しいです

私はDBレベルではなくRubyで多くのことをしているので、これは非常に効率的だとは思いません。

ActiveRecordは単純なクエリには適していますが、物事が複雑になっている場合は、プレーンSQLを使用するのが妥当です。それでは、テストケースに一致するクエリを作成してみましょう。

1)この呼び出しtest("politics people china", true)の場合、クエリは次のようになります。

SELECT DISTINCT ON (AR.id) AR.*
FROM articles AR
  JOIN articles_hashtags AHSH ON AHSH.article_id = AR.id
  JOIN hashtags HSH ON HSH.id = AHSH.hashtag_id
WHERE LOWER(HSH.value) IN ('politics', 'people', 'china')
ORDER BY AR.id;

(結合テーブルの名前がわからないので、名前が付けられていると仮定しますarticles_hashtags)。

無地でシンプルに:私たちは、からデータを取りarticles、内2と合流使用してテーブルarticles_hashtagshashtagsし、where私たちが見てみたいハッシュタグをフィルタリング条件を、。そして最終的には、そのハッシュタグが付いたすべての記事が表示されます。フィルタリングするINハッシュタグの数に関係なく、リストにハッシュタグが1つしかない場合でも、ステートメントは適切に機能します。

DISTINCT ONに注意してください:同じ記事が特定のハッシュタグリストから複数のハッシュタグを持っている場合、結果セットから重複する記事を削除するために必要です。

2)呼び出しの場合test("politics people china", false)、クエリはもう少し複雑です。ハッシュタグを付けた記事は除外する必要があります。したがって、ハッシュタグの異なる記事だけでなく、ハッシュタグのない記事も返す必要があります。物事を単純に保つために、前のクエリを使用できます。

SELECT A.*
FROM articles A
WHERE A.id NOT IN (
    SELECT DISTINCT ON (AR.id) AR.id
    FROM articles AR
      JOIN articles_hashtags AHSH ON AHSH.article_id = AR.id
      JOIN hashtags HSH ON HSH.id = AHSH.hashtag_id
    WHERE LOWER(HSH.value) IN ('politics', 'people', 'china')
    ORDER BY AR.id
);

ここではすべての記事を取得していますが、特定のハッシュタグのいずれかを持っている記事を取得しています。

3)これらのクエリをRubyメソッドに変換すると、次のようになります。

def test3(hashtags, include = true)
  # code guard to prevent SQL-error when there are no hashtags given
  if hashtags.nil? || hashtags.strip.blank?
    return include ? [] : Article.all.to_a
  end

  basic_query = "
    SELECT DISTINCT ON (AR.id) AR.*
    FROM #{Article.table_name} AR
      JOIN articles_hashtags AHSH ON AHSH.article_id = AR.id
      JOIN #{Hashtag.table_name} HSH ON HSH.id = AHSH.hashtag_id
    WHERE LOWER(HSH.value) IN (:hashtags)
    ORDER BY AR.id"

  query = if include
            basic_query
          else
            "SELECT A.*
            FROM #{Article.table_name} A
            WHERE A.id NOT IN (#{basic_query.sub('AR.*', 'AR.id')})"
          end

  hashtag_arr = hashtags.split(' ').map(&:downcase) # to convert hashtags string into a list

  Article.find_by_sql [query, { hashtags: hashtag_arr }]
end

上記のメソッドは、空かどうかに関係なく、条件に一致する記事の配列を返します。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

Javaでドット積メソッドをより速くまたはより効率的にする方法は?

分類Dev

エラーの値のチェックをより効率的にする方法

分類Dev

このユニオンクエリをより効率的にする方法は?

分類Dev

appengineエンティティのget()メソッドとput()メソッドをオーバーライドして、memcacheを使用するようにする効率的な方法はありますか?

分類Dev

右クリックを有効にするより効率的な方法は?

分類Dev

Ruby:「未定義のメソッド」エラー。gsubをより効果的に使用する方法は?

分類Dev

このクエリをより効率的にする方法、またはGoogle App Scriptにする方法は?

分類Dev

JUnitでメソッドを効率的にテストする方法

分類Dev

このMySQLクエリをより効率的にする方法はありますか?

分類Dev

C#ランバクエリをより効率的に作成する方法

分類Dev

Rubyでメソッドの結果をクエリする方法(rails)

分類Dev

SSMS2014でどのクエリがより効率的かを判断する方法

分類Dev

Numpy-メトリックを計算するためのより効率的なコード

分類Dev

Javascriptで.search()メソッドをより効率的に使用するにはどうすればよいですか?

分類Dev

Ectoクエリをより効率的にする

分類Dev

LEFTJOINクエリをより効率的にする

分類Dev

コードをより効率的にリファクタリングする最良の方法は?

分類Dev

2つのメソッドを呼び出す1つのリンクを効率的に組み合わせる方法は?

分類Dev

Djangoクエリセットを効率的に使用する方法

分類Dev

unlistメソッドを使用する代わりに、ネストされたリストをより効率的に1つのリストにフラット化するにはどうすればよいですか?

分類Dev

Mysqlクエリ(複数結合を使用)をより速く、より効率的にする方法

分類Dev

Postgresql:クエリをより効率的にするためのサブクエリの代替手段?

分類Dev

javascriptのIndexOfメソッドは、配列を反復処理するよりも効率的ですか?

分類Dev

ポリモーフィックメソッドの複数の実装に共通するコードを効率的に再利用する

分類Dev

Laravelのメソッドcrudboosterに結合クエリを追加する方法

分類Dev

コードをよりクリーンにするために、非常に大きなパブリッククラスの列挙をそれらを利用するパブリックメソッドの下に配置する効果的で適切な方法はありますか?

分類Dev

ステートレスロジックにEJB @ Aynchronousメソッドを提供する最も効率的な方法

分類Dev

ステートレスロジックにEJB @ Aynchronousメソッドを提供する最も効率的な方法

分類Dev

そのメンバー関数へのメソッド引数をリファクタリングする効率的な方法は?

Related 関連記事

  1. 1

    Javaでドット積メソッドをより速くまたはより効率的にする方法は?

  2. 2

    エラーの値のチェックをより効率的にする方法

  3. 3

    このユニオンクエリをより効率的にする方法は?

  4. 4

    appengineエンティティのget()メソッドとput()メソッドをオーバーライドして、memcacheを使用するようにする効率的な方法はありますか?

  5. 5

    右クリックを有効にするより効率的な方法は?

  6. 6

    Ruby:「未定義のメソッド」エラー。gsubをより効果的に使用する方法は?

  7. 7

    このクエリをより効率的にする方法、またはGoogle App Scriptにする方法は?

  8. 8

    JUnitでメソッドを効率的にテストする方法

  9. 9

    このMySQLクエリをより効率的にする方法はありますか?

  10. 10

    C#ランバクエリをより効率的に作成する方法

  11. 11

    Rubyでメソッドの結果をクエリする方法(rails)

  12. 12

    SSMS2014でどのクエリがより効率的かを判断する方法

  13. 13

    Numpy-メトリックを計算するためのより効率的なコード

  14. 14

    Javascriptで.search()メソッドをより効率的に使用するにはどうすればよいですか?

  15. 15

    Ectoクエリをより効率的にする

  16. 16

    LEFTJOINクエリをより効率的にする

  17. 17

    コードをより効率的にリファクタリングする最良の方法は?

  18. 18

    2つのメソッドを呼び出す1つのリンクを効率的に組み合わせる方法は?

  19. 19

    Djangoクエリセットを効率的に使用する方法

  20. 20

    unlistメソッドを使用する代わりに、ネストされたリストをより効率的に1つのリストにフラット化するにはどうすればよいですか?

  21. 21

    Mysqlクエリ(複数結合を使用)をより速く、より効率的にする方法

  22. 22

    Postgresql:クエリをより効率的にするためのサブクエリの代替手段?

  23. 23

    javascriptのIndexOfメソッドは、配列を反復処理するよりも効率的ですか?

  24. 24

    ポリモーフィックメソッドの複数の実装に共通するコードを効率的に再利用する

  25. 25

    Laravelのメソッドcrudboosterに結合クエリを追加する方法

  26. 26

    コードをよりクリーンにするために、非常に大きなパブリッククラスの列挙をそれらを利用するパブリックメソッドの下に配置する効果的で適切な方法はありますか?

  27. 27

    ステートレスロジックにEJB @ Aynchronousメソッドを提供する最も効率的な方法

  28. 28

    ステートレスロジックにEJB @ Aynchronousメソッドを提供する最も効率的な方法

  29. 29

    そのメンバー関数へのメソッド引数をリファクタリングする効率的な方法は?

ホットタグ

アーカイブ