Select distinct on 无法正常工作 rails 4.2.5
Select distinct on does not work properly rails 4.2.5
我有这两个型号:
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
范围,那么所有的工作都像一个魅力。
但我希望每个 post 从搜索结果中检索最后添加的评论。为此,我构建了 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" = ORDER BY created_at DESC, rank DESC, id DESC [["post_id", 7]]
结果是一个空数组 :(.
我无法理解我做错了什么[显然我在这里做了一些愚蠢的事情:( ]。
你能帮我解决这个问题吗?
这意味着您的查询(复杂的查询)找到了一些 Post,第一个的 ID 为 7。然后您询问了关于 post 的所有评论,它有没有评论。这一切似乎都井井有条。 SQL 是不同的,因为它是一个不同的问题。不是,"Find the posts with 'My post name'."是"Find the comments for post 7."
编辑:事情变得混乱的原因是因为您正在 SELECT
ing comments.*
,而 ActiveRecord 使用它来实例化 Post
对象(不是 Comment
个对象)。所以你得到 comments.id
of 7 并且 ActiveRecord 认为那是 Post 的 id。此外,选择 post_id
和 post_name
也没有意义。这应该可以防止 ActiveRecord 混淆:
select('DISTINCT ON (comments.post_id) posts.*')
而且:由于您只是搜索 post 的名称,我完全不确定您为什么要加入 comments
。 . . .
我有这两个型号:
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
范围,那么所有的工作都像一个魅力。
但我希望每个 post 从搜索结果中检索最后添加的评论。为此,我构建了 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" = ORDER BY created_at DESC, rank DESC, id DESC [["post_id", 7]]
结果是一个空数组 :(.
我无法理解我做错了什么[显然我在这里做了一些愚蠢的事情:( ]。
你能帮我解决这个问题吗?
这意味着您的查询(复杂的查询)找到了一些 Post,第一个的 ID 为 7。然后您询问了关于 post 的所有评论,它有没有评论。这一切似乎都井井有条。 SQL 是不同的,因为它是一个不同的问题。不是,"Find the posts with 'My post name'."是"Find the comments for post 7."
编辑:事情变得混乱的原因是因为您正在 SELECT
ing comments.*
,而 ActiveRecord 使用它来实例化 Post
对象(不是 Comment
个对象)。所以你得到 comments.id
of 7 并且 ActiveRecord 认为那是 Post 的 id。此外,选择 post_id
和 post_name
也没有意义。这应该可以防止 ActiveRecord 混淆:
select('DISTINCT ON (comments.post_id) posts.*')
而且:由于您只是搜索 post 的名称,我完全不确定您为什么要加入 comments
。 . . .