1

私はこの2つのモデルを持っています:

class Comment < ActiveRecord::Base
  belongs_to :post
end

class Post < ActiveRecord::Base
  include PgSearch
  has_many :comments, dependent: destroy

  pg_search_scope :search_tsv, against: [:name], 
                    using: { tsearch: { 
                              tsvector_column: 'tsv', 
                              dictionary: 'english', 
                              prefix: true, any_word: true
                             } 
                            }

 scope :full_search, ->(q) {
   select('DISTINCT ON (comments.post_id) comments.*, posts.name as post_name, posts.id as post_id')
   .order('comments.post_id, comments.created_at DESC')
   .search_tsv(q)
   .joins('LEFT JOIN comments on comments.post_id = posts.id')
 }
end

ご覧のとおり、Post モデルに全文検索を実装しようとしています。TSVECTOR 列とそれを更新するトリガーを作成しましたが、search_tsvスコープのみを使用する場合、すべてが魅力のように機能します。

しかし、検索結果からの投稿ごとに、最後に追加されたコメントを取得したいと考えています。そのために、full_searchスコープを構築しました。

このスコープを使用しようとすると、生成される SQL クエリは次のようになります。

> Post.full_search('My post name').to_sql
> SELECT DISTINCT ON (comments.post_id) comments.*, 
         posts.name as post_name, potst.id as post_id 
  FROM "posts" 
  INNER JOIN (SELECT "posts"."id" AS pg_search_id, (ts_rank(("posts"."tsv"), (to_tsquery('english', ''' ' || 'My' || ' ''' || ':*') || to_tsquery('english', ''' ' || 'post' || ' ''' || ':*') || to_tsquery('english', ''' ' || 'name' || ' ''' || ':*')), 0)) AS rank FROM "posts" WHERE ((("posts"."tsv") @@ (to_tsquery('english', ''' ' || 'My' || ' ''' || ':*') || to_tsquery('english', ''' ' || 'post' || ' ''' || ':*') || to_tsquery('english', ''' ' || 'name' || ' ''' || ':*'))))) AS pg_search_00699f600cf5a0ff57479a ON "posts"."id" = pg_search_00699f600cf5a0ff57479a.pg_search_id 
 LEFT JOIN comments on comments.post_id = posts.id  
 ORDER BY comments.post_id, comments.created_at DESC, pg_search_00699f600cf5a0ff57479a.rank DESC, "posts"."id" ASC

これは私にとっては問題ありません。しかし、検索コントローラーでこのスコープを使用しようとすると、結果が奇妙になります...

posts = Post.full_search('My post name')
k = posts.first.comments
...

次の SQL クエリが生成されます。

SELECT "comments".* FROM "comments" WHERE "comments"."post_id" = $1  ORDER BY created_at DESC, rank DESC, id DESC  [["post_id", 7]]

結果は空の配列です:(。

私は自分が何を間違っているのか理解できませんでした[明らかに私はここで何かばかげたことをしています:(]。

これを修正するのを手伝ってもらえますか?

4

1 に答える 1

2

これは、クエリ (複雑なクエリ) でいくつかの投稿が見つかり、最初の投稿の ID が 7 だったことを意味します。次に、その投稿に対するすべてのコメントを要求しましたが、コメントはありませんでした。それはすべて順調に思えます。それは別の質問であるため、SQLは異なります。「『私の投稿名』で投稿を探す」ではありません。それは「投稿 7 のコメントを探す」です。

編集: 物事が混乱している理由は、あなたがSELECTingしているためcomments.*であり、ActiveRecord はそれを使用してPostオブジェクト (オブジェクトではないComment) をインスタンス化します。つまり、あなたはcomments.id7 を取得しており、ActiveRecord はそれが投稿の ID であると考えています。また、 と を選択post_idしても意味がありませんpost_name。これにより、ActiveRecord が混乱するのを防ぐことができます。

   select('DISTINCT ON (comments.post_id) posts.*')

また、投稿の名前で検索しているだけなので、なぜ参加しているのかまったくわかりませんcomments。. . .

于 2016-03-19T04:19:18.010 に答える