Skip to content

Commit 1b79287

Browse files
committed
Merge upstream PR Casecommons#542
2 parents 23b2a4c + 8617373 commit 1b79287

4 files changed

Lines changed: 36 additions & 7 deletions

File tree

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,6 +1203,19 @@ shirt_brands = ShirtBrand.search_by_name("Penguin")
12031203
.group("shirt_brands.id, #{PgSearch::Configuration.alias('shirt_brands')}.rank")
12041204
```
12051205

1206+
#### Scoping search rank subqueries
1207+
1208+
It may be necessary to limit the scope of a rank subquery for performance reasons.
1209+
The subquery scope relation object is accessed by passing a block to the search
1210+
method.
1211+
1212+
```ruby
1213+
shirt_manufacturer = ShirtManufacturer.find_by(name: "Hypercolor Sportswear Co")
1214+
shirt_brands = ShirtBrand.search_by_name("Penguin") do |subquery_relation|
1215+
subquery_relation.where(shirt_manufacturer: shirt_manufacturer)
1216+
end.with_pg_search_rank
1217+
```
1218+
12061219
## ATTRIBUTIONS
12071220

12081221
PgSearch would not have been possible without inspiration from texticle (now renamed

lib/pg_search/model.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ def pg_search_scope(name, options)
1414
raise ArgumentError, "pg_search_scope expects a Hash or Proc"
1515
end
1616

17-
define_singleton_method(name) do |*args|
17+
define_singleton_method(name) do |*args, &block|
1818
config = Configuration.new(options_proc.call(*args), self)
1919
scope_options = ScopeOptions.new(config)
20-
scope_options.apply(self)
20+
scope_options.apply(self, &block)
2121
end
2222
end
2323

lib/pg_search/scope_options.rb

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ def initialize(config)
1212
@feature_options = config.feature_options
1313
end
1414

15-
def apply(scope)
15+
def apply(scope, &block)
1616
scope = include_table_aliasing_for_rank(scope)
1717
rank_table_alias = scope.pg_search_rank_table_alias(include_counter: true)
1818

1919
scope
20-
.joins(rank_join(rank_table_alias))
20+
.joins(rank_join(rank_table_alias, &block))
2121
.order(Arel.sql("#{rank_table_alias}.rank DESC, #{order_within_rank}"))
2222
.extend(WithPgSearchRank)
2323
.extend(WithPgSearchHighlight[feature_for(:tsearch)])
@@ -80,14 +80,16 @@ def increment_counter
8080
delegate :connection, :quoted_table_name, to: :model
8181

8282
def subquery
83-
model
83+
relation = model
8484
.unscoped
8585
.select("#{primary_key} AS pg_search_id")
8686
.select("#{rank} AS rank")
8787
.joins(subquery_join)
8888
.where(conditions)
8989
.limit(nil)
9090
.offset(nil)
91+
92+
block_given? ? yield(relation) : relation
9193
end
9294

9395
def conditions
@@ -163,8 +165,8 @@ def rank
163165
end
164166
end
165167

166-
def rank_join(rank_table_alias)
167-
"INNER JOIN (#{subquery.to_sql}) AS #{rank_table_alias} ON #{primary_key} = #{rank_table_alias}.pg_search_id"
168+
def rank_join(rank_table_alias, &block)
169+
"INNER JOIN (#{subquery(&block).to_sql}) AS #{rank_table_alias} ON #{primary_key} = #{rank_table_alias}.pg_search_id"
168170
end
169171

170172
def include_table_aliasing_for_rank(scope)

spec/integration/pg_search_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,20 @@
439439
expect(results).to eq([winner, loser])
440440
end
441441

442+
it "is filterable in sub-select when sorted by rank" do
443+
loser = ModelWithPgSearch.create!(content: "foo", parent_model_id: 1)
444+
winner = ModelWithPgSearch.create!(content: "foo foo", parent_model_id: 1)
445+
filtered = ModelWithPgSearch.create!(content: "foo foo foo", parent_model_id: 2)
446+
447+
448+
results = ModelWithPgSearch.search_content("foo") do |subquery_relation|
449+
subquery_relation.where(parent_model_id: 1)
450+
end.with_pg_search_rank
451+
452+
expect(results).to_not include(filtered)
453+
expect(results).to eq([winner, loser])
454+
end
455+
442456
it "preserves column selection when with_pg_search_rank is chained after a select()" do
443457
ModelWithPgSearch.create!(title: "foo", content: "bar")
444458

0 commit comments

Comments
 (0)