组合搜索范围时出错
Error when combining search scopes
我有一个 Web 服务,允许客户搜索带有查询 parameters.It 的文章,如果只包含一个参数,则工作正常,但如果我结合使用 search_query
和 category
,则会失败。这是根据Comfortable_Mexican_Sofa where for_category发现的。即使我删除了 order
语句,我也会收到此错误。
错误
PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY
expressions must appear in select list LINE 1:
...ms_categories"."label" = 'Company News' ORDER BY pg_search_...
^ : SELECT DISTINCT "comfy_cms_pages".* FROM "comfy_cms_pages" INNER JOIN
"comfy_cms_categorizations" ON
"comfy_cms_categorizations"."categorized_id" = "comfy_cms_pages"."id"
AND "comfy_cms_categorizations"."categorized_type" = INNER JOIN
"comfy_cms_categories" ON "comfy_cms_categories"."id" =
"comfy_cms_categorizations"."category_id" INNER JOIN (SELECT
"comfy_cms_pages"."id" AS pg_search_id,
(ts_rank((to_tsvector('simple',
coalesce("comfy_cms_pages"."content_cache"::text, '')) ||
to_tsvector('simple', coalesce("comfy_cms_pages"."label"::text, ''))),
(to_tsquery('simple', ''' ' || 'austin' || ' ''' || ':')), 0)) AS
rank FROM "comfy_cms_pages" WHERE (((to_tsvector('simple',
coalesce("comfy_cms_pages"."content_cache"::text, '')) ||
to_tsvector('simple', coalesce("comfy_cms_pages"."label"::text, '')))
@@ (to_tsquery('simple', ''' ' || 'austin' || ' ''' || ':')))))
pg_search_comfy_cms_pages ON "comfy_cms_pages"."id" =
pg_search_comfy_cms_pages.pg_search_id WHERE (layout_id = '1' AND
is_published = 't') AND "comfy_cms_categories"."label" = 'Company
News' ORDER BY pg_search_comfy_cms_pages.rank DESC,
"comfy_cms_pages"."id" ASC, "comfy_cms_pages"."created_at" DESC
app/models/article.rb
class Article < Comfy::Cms::Page
cms_is_categorized
include PgSearch
pg_search_scope :search_by_keywords, against: [:content_cache, :label], using: { tsearch: { any_word: true, prefix: true } }
app/commands/search_articles_command.rb
class SearchArticlesCommand
def initialize(params = {})
@since = params[:since_date]
@keys = params[:search_query]
@category = params[:category]
end
def execute
Article.unscoped do
query = if @since.present?
Article.article.since_date(@since)
else
Article.published_article
end
query = query.for_category(@category) if @category.present?
query = query.search_by_keywords(@keys) if @keys.present?
query.where('').order(created_at: :desc)
end
end
end
comfortable-mexican-sofa/lib/comfortable_mexican_sofa/extensions/is_categorized.rb
module ComfortableMexicanSofa::IsCategorized
def self.included(base)
base.send :extend, ClassMethods
end
module ClassMethods
def cms_is_categorized
include ComfortableMexicanSofa::IsCategorized::InstanceMethods
has_many :categorizations,
:as => :categorized,
:class_name => 'Comfy::Cms::Categorization',
:dependent => :destroy
has_many :categories,
:through => :categorizations,
:class_name => 'Comfy::Cms::Category'
attr_accessor :category_ids
after_save :sync_categories
scope :for_category, lambda { |*categories|
if (categories = [categories].flatten.compact).present?
self.distinct.
joins(:categorizations => :category).
where('comfy_cms_categories.label' => categories)
end
}
end
end
module InstanceMethods
def sync_categories
(self.category_ids || {}).each do |category_id, flag|
case flag.to_i
when 1
if category = Comfy::Cms::Category.find_by_id(category_id)
category.categorizations.create(:categorized => self)
end
when 0
self.categorizations.where(:category_id => category_id).destroy_all
end
end
end
end
end
ActiveRecord::Base.send :include, ComfortableMexicanSofa::IsCategorized
更新错误
PG::SyntaxError: ERROR: syntax error at or near "."
LINE 4: ...e = 'Class' AND categorized_id = 'comfy_cms_pages'.'id' AND ...
^
: SELECT "comfy_cms_pages".* FROM "comfy_cms_pages" INNER JOIN (SELECT "comfy_cms_pages"."id" AS pg_search_id, (ts_rank((to_tsvector('simple', coalesce("comfy_cms_pages"."content_cache"::text, '')) || to_tsvector('simple', coalesce("comfy_cms_pages"."label"::text, ''))), (to_tsquery('simple', ''' ' || 'austin' || ' ''' || ':*')), 0)) AS rank FROM "comfy_cms_pages" WHERE (((to_tsvector('simple', coalesce("comfy_cms_pages"."content_cache"::text, '')) || to_tsvector('simple', coalesce("comfy_cms_pages"."label"::text, ''))) @@ (to_tsquery('simple', ''' ' || 'austin' || ' ''' || ':*'))))) pg_search_comfy_cms_pages ON "comfy_cms_pages"."id" = pg_search_comfy_cms_pages.pg_search_id WHERE "comfy_cms_pages"."layout_id" = AND "comfy_cms_pages"."is_published" = AND (
EXISTS (
SELECT 1 FROM categorizations
WHERE categorized_type = 'Class' AND categorized_id = 'comfy_cms_pages'.'id' AND category_id IN (2)
)) ORDER BY pg_search_comfy_cms_pages.rank DESC, "comfy_cms_pages"."id" ASC
工作解决方案但不是一个范围,必须小心命令它被调用
def self.for_category(_category)
Comfy::Cms::Categorization.includes(:category).references(:category).select(:categorized).pluck(:categorized_id)
find(ids)
end
我认为最好覆盖 for_category
CMS 的内置过滤器。该查询中的联接过多。
像这样覆盖 for_category
:
scope :for_category, lambda { |*categories|
if (categories = [categories].flatten.compact).present?
self_ids = "{connection.quote_table_name(self.table_name)}.#{connection.quote_column_name(self.primary_key)}"
self.where(
"EXISTS (" +
Comfy::Cms::Categorization.select('1').
where(categorized_type: self.name).
where('categorized_id' => self_ids).
where(category_id: Comfy::Cms::Category.where(label: categories).pluck(:id)).to_sql +
")"
)
end
}
更多关于 SQL EXISTS
用法的 Rails 你可以在我的 .
中阅读
您可以在 question and answer here.
中阅读有关您为何遇到该错误的更多信息
具体来说,pg_search
希望按排名对结果进行排序。而 for_category
只想 select 文章的不同字段,而不关心搜索排名。更改其代码以使用简单的 EXISTS
而不是复杂的 JOIN
查询将解决此问题。
我能够通过将 reorder
应用于 pg_search 结果的结果来解决这个问题。
search_command.rb
class SearchArticlesCommand
def initialize(params = {})
@since = params['since_date']
@keys = params['search_query']
@category = params['category']
end
def execute
Article.unscoped do
query = Article.article
query = if @since.present?
query.since_date(@since)
else
query.published
end
query = query.for_category(@category) if @category.present?
query = query.search_by_keywords(@keys).reorder('updated_at DESC') if @keys.present?
query
end
end
end
我也覆盖了for_category(不需要)
article.rb
scope :for_category, (lambda do |category|
published
.joins(:categories)
.group(:id)
.where('comfy_cms_categories.label' => category)
.select('comfy_cms_pages.*')
end)
我有一个 Web 服务,允许客户搜索带有查询 parameters.It 的文章,如果只包含一个参数,则工作正常,但如果我结合使用 search_query
和 category
,则会失败。这是根据Comfortable_Mexican_Sofa where for_category发现的。即使我删除了 order
语句,我也会收到此错误。
错误
PG::InvalidColumnReference: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list LINE 1: ...ms_categories"."label" = 'Company News' ORDER BY pg_search_... ^ : SELECT DISTINCT "comfy_cms_pages".* FROM "comfy_cms_pages" INNER JOIN "comfy_cms_categorizations" ON "comfy_cms_categorizations"."categorized_id" = "comfy_cms_pages"."id" AND "comfy_cms_categorizations"."categorized_type" = INNER JOIN "comfy_cms_categories" ON "comfy_cms_categories"."id" = "comfy_cms_categorizations"."category_id" INNER JOIN (SELECT "comfy_cms_pages"."id" AS pg_search_id, (ts_rank((to_tsvector('simple', coalesce("comfy_cms_pages"."content_cache"::text, '')) || to_tsvector('simple', coalesce("comfy_cms_pages"."label"::text, ''))), (to_tsquery('simple', ''' ' || 'austin' || ' ''' || ':')), 0)) AS rank FROM "comfy_cms_pages" WHERE (((to_tsvector('simple', coalesce("comfy_cms_pages"."content_cache"::text, '')) || to_tsvector('simple', coalesce("comfy_cms_pages"."label"::text, ''))) @@ (to_tsquery('simple', ''' ' || 'austin' || ' ''' || ':'))))) pg_search_comfy_cms_pages ON "comfy_cms_pages"."id" = pg_search_comfy_cms_pages.pg_search_id WHERE (layout_id = '1' AND is_published = 't') AND "comfy_cms_categories"."label" = 'Company News' ORDER BY pg_search_comfy_cms_pages.rank DESC, "comfy_cms_pages"."id" ASC, "comfy_cms_pages"."created_at" DESC
app/models/article.rb
class Article < Comfy::Cms::Page
cms_is_categorized
include PgSearch
pg_search_scope :search_by_keywords, against: [:content_cache, :label], using: { tsearch: { any_word: true, prefix: true } }
app/commands/search_articles_command.rb
class SearchArticlesCommand
def initialize(params = {})
@since = params[:since_date]
@keys = params[:search_query]
@category = params[:category]
end
def execute
Article.unscoped do
query = if @since.present?
Article.article.since_date(@since)
else
Article.published_article
end
query = query.for_category(@category) if @category.present?
query = query.search_by_keywords(@keys) if @keys.present?
query.where('').order(created_at: :desc)
end
end
end
comfortable-mexican-sofa/lib/comfortable_mexican_sofa/extensions/is_categorized.rb
module ComfortableMexicanSofa::IsCategorized
def self.included(base)
base.send :extend, ClassMethods
end
module ClassMethods
def cms_is_categorized
include ComfortableMexicanSofa::IsCategorized::InstanceMethods
has_many :categorizations,
:as => :categorized,
:class_name => 'Comfy::Cms::Categorization',
:dependent => :destroy
has_many :categories,
:through => :categorizations,
:class_name => 'Comfy::Cms::Category'
attr_accessor :category_ids
after_save :sync_categories
scope :for_category, lambda { |*categories|
if (categories = [categories].flatten.compact).present?
self.distinct.
joins(:categorizations => :category).
where('comfy_cms_categories.label' => categories)
end
}
end
end
module InstanceMethods
def sync_categories
(self.category_ids || {}).each do |category_id, flag|
case flag.to_i
when 1
if category = Comfy::Cms::Category.find_by_id(category_id)
category.categorizations.create(:categorized => self)
end
when 0
self.categorizations.where(:category_id => category_id).destroy_all
end
end
end
end
end
ActiveRecord::Base.send :include, ComfortableMexicanSofa::IsCategorized
更新错误
PG::SyntaxError: ERROR: syntax error at or near "."
LINE 4: ...e = 'Class' AND categorized_id = 'comfy_cms_pages'.'id' AND ...
^
: SELECT "comfy_cms_pages".* FROM "comfy_cms_pages" INNER JOIN (SELECT "comfy_cms_pages"."id" AS pg_search_id, (ts_rank((to_tsvector('simple', coalesce("comfy_cms_pages"."content_cache"::text, '')) || to_tsvector('simple', coalesce("comfy_cms_pages"."label"::text, ''))), (to_tsquery('simple', ''' ' || 'austin' || ' ''' || ':*')), 0)) AS rank FROM "comfy_cms_pages" WHERE (((to_tsvector('simple', coalesce("comfy_cms_pages"."content_cache"::text, '')) || to_tsvector('simple', coalesce("comfy_cms_pages"."label"::text, ''))) @@ (to_tsquery('simple', ''' ' || 'austin' || ' ''' || ':*'))))) pg_search_comfy_cms_pages ON "comfy_cms_pages"."id" = pg_search_comfy_cms_pages.pg_search_id WHERE "comfy_cms_pages"."layout_id" = AND "comfy_cms_pages"."is_published" = AND (
EXISTS (
SELECT 1 FROM categorizations
WHERE categorized_type = 'Class' AND categorized_id = 'comfy_cms_pages'.'id' AND category_id IN (2)
)) ORDER BY pg_search_comfy_cms_pages.rank DESC, "comfy_cms_pages"."id" ASC
工作解决方案但不是一个范围,必须小心命令它被调用
def self.for_category(_category)
Comfy::Cms::Categorization.includes(:category).references(:category).select(:categorized).pluck(:categorized_id)
find(ids)
end
我认为最好覆盖 for_category
CMS 的内置过滤器。该查询中的联接过多。
像这样覆盖 for_category
:
scope :for_category, lambda { |*categories|
if (categories = [categories].flatten.compact).present?
self_ids = "{connection.quote_table_name(self.table_name)}.#{connection.quote_column_name(self.primary_key)}"
self.where(
"EXISTS (" +
Comfy::Cms::Categorization.select('1').
where(categorized_type: self.name).
where('categorized_id' => self_ids).
where(category_id: Comfy::Cms::Category.where(label: categories).pluck(:id)).to_sql +
")"
)
end
}
更多关于 SQL EXISTS
用法的 Rails 你可以在我的
您可以在 question and answer here.
中阅读有关您为何遇到该错误的更多信息具体来说,pg_search
希望按排名对结果进行排序。而 for_category
只想 select 文章的不同字段,而不关心搜索排名。更改其代码以使用简单的 EXISTS
而不是复杂的 JOIN
查询将解决此问题。
我能够通过将 reorder
应用于 pg_search 结果的结果来解决这个问题。
search_command.rb
class SearchArticlesCommand
def initialize(params = {})
@since = params['since_date']
@keys = params['search_query']
@category = params['category']
end
def execute
Article.unscoped do
query = Article.article
query = if @since.present?
query.since_date(@since)
else
query.published
end
query = query.for_category(@category) if @category.present?
query = query.search_by_keywords(@keys).reorder('updated_at DESC') if @keys.present?
query
end
end
end
我也覆盖了for_category(不需要)
article.rb
scope :for_category, (lambda do |category|
published
.joins(:categories)
.group(:id)
.where('comfy_cms_categories.label' => category)
.select('comfy_cms_pages.*')
end)