pg_search:"multisearchable" 个结果的排序
pg_search: ordering of "multisearchable" results
我正在使用 Rails 4.2.4 和 pg_search 1.0.5。
class Advert < ActiveRecord::Base
include PgSearch
multisearchable :against => [:title, :body]
end
我想在我的广告记录的 :created_at
日期之前订购 pg_search 结果。从逻辑上讲,在我看来,以下内容可行 (:asc
):
> @pgs = PgSearch.multisearch('55948189').order(created_at: :asc)
PgSearch::Document Load (136.1ms) SELECT "pg_search_documents".* FROM "pg_search_documents" INNER JOIN (SELECT "pg_search_documents"."id" AS pg_search_id, (ts_rank((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))), (to_tsquery('simple', ''' ' || '55948189' || ' ''')), 0)) AS rank FROM "pg_search_documents" WHERE (((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || '55948189' || ' '''))))) AS pg_search_ce9b9dd18c5c0023f2116f ON "pg_search_documents"."id" = pg_search_ce9b9dd18c5c0023f2116f.pg_search_id ORDER BY pg_search_ce9b9dd18c5c0023f2116f.rank DESC, "pg_search_documents"."id" ASC, "pg_search_documents"."created_at" ASC
=> #<ActiveRecord::Relation [
#<PgSearch::Document id: 3148, content: "Aleksandra | Tallinn | 55948189 Simpatichnaja i se...", searchable_id: 3148, searchable_type: "Advert", created_at: "2015-10-01 11:44:06", updated_at: "2015-10-01 11:44:30">,
#<PgSearch::Document id: 3275, content: "Aleksandra | Tallinn | 55948189 Simpatichnaja i se...", searchable_id: 3275, searchable_type: "Advert", created_at: "2015-10-02 11:05:49", updated_at: "2015-10-02 11:28:48">]>
但是相反的顺序 (:desc
) 产生相同的结果:
> @pgs = PgSearch.multisearch('55948189').order(created_at: :desc)
PgSearch::Document Load (108.4ms) SELECT "pg_search_documents".* FROM "pg_search_documents" INNER JOIN (SELECT "pg_search_documents"."id" AS pg_search_id, (ts_rank((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))), (to_tsquery('simple', ''' ' || '55948189' || ' ''')), 0)) AS rank FROM "pg_search_documents" WHERE (((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || '55948189' || ' '''))))) AS pg_search_ce9b9dd18c5c0023f2116f ON "pg_search_documents"."id" = pg_search_ce9b9dd18c5c0023f2116f.pg_search_id ORDER BY pg_search_ce9b9dd18c5c0023f2116f.rank DESC, "pg_search_documents"."id" ASC, "pg_search_documents"."created_at" DESC
=> #<ActiveRecord::Relation [
#<PgSearch::Document id: 3148, content: "Aleksandra | Tallinn | 55948189 Simpatichnaja i se...", searchable_id: 3148, searchable_type: "Advert", created_at: "2015-10-01 11:44:06", updated_at: "2015-10-01 11:44:30">,
#<PgSearch::Document id: 3275, content: "Aleksandra | Tallinn | 55948189 Simpatichnaja i se...", searchable_id: 3275, searchable_type: "Advert", created_at: "2015-10-02 11:05:49", updated_at: "2015-10-02 11:28:48">]>
谁能解释一下如何在 :created_at
日期之前对我的搜索结果进行排序?
更新 1:是否有可能结果的顺序由 pg_search
固定并且没有有什么方法可以按 'created_at` 订购吗?
我现在更仔细地阅读了文档,发现了这个语句:“默认情况下,pg_search 根据可搜索文本和查询之间的 :tsearch 相似性对结果进行排名。要使用不同的排名算法,您可以将 :ranked_by 选项传递给 pg_search_scope。"(参见 https://github.com/Casecommons/pg_search)
有一个简单的答案,但不适用于 "multisearchable"。
首先,我需要从 "multisearchable"(适用于多个模型)更改为 "pg_search_scope"(仅在单个模型中搜索)。
其次,我需要使用 :order_within_rank
。由于结果都是搜索词的 100% 匹配,因此它们根据 pg_search
具有相同的排名。 :order_within_rank
作为决胜局给予次要排名。
class Advert < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_full_advert,
:against => [:title, :body],
:order_within_rank => "adverts.created_at DESC"
end
我可能迟到了 5 年,但我偶然发现了同样的问题并想出了你该怎么做。
简短的回答 - 将您的查询,即 PgSearch.multisearch('55948189')
转换为数组。
我的例子:
@results = PgSearch.multisearch(params[:main_search][:query])
虽然您无法对 @results
进行分组或排序,但您可以使用 @results.to_a
.
进行分组或排序
在我的例子中,我有两个模型 - Products
和 Manufacturers
(制造商生产产品),我想首先在我的搜索结果中显示 所有产品结果 然后才 所有制造商结果。
首先,定义一个数组作为排序依据:
sorting_order = ["Manufacturer", "Product"]
然后
@results.to_a.sort_by { |x| sorting_order.index x.searchable_type }
(注意:serachable_type
是gem迁移生成的PgSearch::Document
的默认列)
我正在使用 Rails 4.2.4 和 pg_search 1.0.5。
class Advert < ActiveRecord::Base
include PgSearch
multisearchable :against => [:title, :body]
end
我想在我的广告记录的 :created_at
日期之前订购 pg_search 结果。从逻辑上讲,在我看来,以下内容可行 (:asc
):
> @pgs = PgSearch.multisearch('55948189').order(created_at: :asc)
PgSearch::Document Load (136.1ms) SELECT "pg_search_documents".* FROM "pg_search_documents" INNER JOIN (SELECT "pg_search_documents"."id" AS pg_search_id, (ts_rank((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))), (to_tsquery('simple', ''' ' || '55948189' || ' ''')), 0)) AS rank FROM "pg_search_documents" WHERE (((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || '55948189' || ' '''))))) AS pg_search_ce9b9dd18c5c0023f2116f ON "pg_search_documents"."id" = pg_search_ce9b9dd18c5c0023f2116f.pg_search_id ORDER BY pg_search_ce9b9dd18c5c0023f2116f.rank DESC, "pg_search_documents"."id" ASC, "pg_search_documents"."created_at" ASC
=> #<ActiveRecord::Relation [
#<PgSearch::Document id: 3148, content: "Aleksandra | Tallinn | 55948189 Simpatichnaja i se...", searchable_id: 3148, searchable_type: "Advert", created_at: "2015-10-01 11:44:06", updated_at: "2015-10-01 11:44:30">,
#<PgSearch::Document id: 3275, content: "Aleksandra | Tallinn | 55948189 Simpatichnaja i se...", searchable_id: 3275, searchable_type: "Advert", created_at: "2015-10-02 11:05:49", updated_at: "2015-10-02 11:28:48">]>
但是相反的顺序 (:desc
) 产生相同的结果:
> @pgs = PgSearch.multisearch('55948189').order(created_at: :desc)
PgSearch::Document Load (108.4ms) SELECT "pg_search_documents".* FROM "pg_search_documents" INNER JOIN (SELECT "pg_search_documents"."id" AS pg_search_id, (ts_rank((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))), (to_tsquery('simple', ''' ' || '55948189' || ' ''')), 0)) AS rank FROM "pg_search_documents" WHERE (((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))) @@ (to_tsquery('simple', ''' ' || '55948189' || ' '''))))) AS pg_search_ce9b9dd18c5c0023f2116f ON "pg_search_documents"."id" = pg_search_ce9b9dd18c5c0023f2116f.pg_search_id ORDER BY pg_search_ce9b9dd18c5c0023f2116f.rank DESC, "pg_search_documents"."id" ASC, "pg_search_documents"."created_at" DESC
=> #<ActiveRecord::Relation [
#<PgSearch::Document id: 3148, content: "Aleksandra | Tallinn | 55948189 Simpatichnaja i se...", searchable_id: 3148, searchable_type: "Advert", created_at: "2015-10-01 11:44:06", updated_at: "2015-10-01 11:44:30">,
#<PgSearch::Document id: 3275, content: "Aleksandra | Tallinn | 55948189 Simpatichnaja i se...", searchable_id: 3275, searchable_type: "Advert", created_at: "2015-10-02 11:05:49", updated_at: "2015-10-02 11:28:48">]>
谁能解释一下如何在 :created_at
日期之前对我的搜索结果进行排序?
更新 1:是否有可能结果的顺序由 pg_search
固定并且没有有什么方法可以按 'created_at` 订购吗?
我现在更仔细地阅读了文档,发现了这个语句:“默认情况下,pg_search 根据可搜索文本和查询之间的 :tsearch 相似性对结果进行排名。要使用不同的排名算法,您可以将 :ranked_by 选项传递给 pg_search_scope。"(参见 https://github.com/Casecommons/pg_search)
有一个简单的答案,但不适用于 "multisearchable"。
首先,我需要从 "multisearchable"(适用于多个模型)更改为 "pg_search_scope"(仅在单个模型中搜索)。
其次,我需要使用 :order_within_rank
。由于结果都是搜索词的 100% 匹配,因此它们根据 pg_search
具有相同的排名。 :order_within_rank
作为决胜局给予次要排名。
class Advert < ActiveRecord::Base
include PgSearch
pg_search_scope :search_by_full_advert,
:against => [:title, :body],
:order_within_rank => "adverts.created_at DESC"
end
我可能迟到了 5 年,但我偶然发现了同样的问题并想出了你该怎么做。
简短的回答 - 将您的查询,即 PgSearch.multisearch('55948189')
转换为数组。
我的例子:
@results = PgSearch.multisearch(params[:main_search][:query])
虽然您无法对 @results
进行分组或排序,但您可以使用 @results.to_a
.
在我的例子中,我有两个模型 - Products
和 Manufacturers
(制造商生产产品),我想首先在我的搜索结果中显示 所有产品结果 然后才 所有制造商结果。
首先,定义一个数组作为排序依据:
sorting_order = ["Manufacturer", "Product"]
然后
@results.to_a.sort_by { |x| sorting_order.index x.searchable_type }
(注意:serachable_type
是gem迁移生成的PgSearch::Document
的默认列)