Reputation: 731
I'm trying to achieve a specific search in my application, and I've run into a bit of trouble.
I want the first results in my search to contain the phrase that was searched for first, instead of just containing it.
For example, if I search for parts in my application, I get these results:
Add-On Windshield Wiper Kit
Turn Signal / Headlight / Windshield Wiper/Washer Combination Lever Set
Turn Signal / Headlight / Windshield Wiper/Washer Combination Switch and Lever Set
Windshield Wiper / Washer Circuit Breaker
Windshield Wiper / Washer Dash Indicator Light
Windshield Wiper Arm
Whereas I'm trying to achieve something like this:
Windshield Wiper Arm
Windshield Wiper / Washer Circuit Breaker
Windshield Wiper / Washer Dash Indicator Light
Add-On Windshield Wiper Kit
Turn Signal / Headlight / Windshield Wiper/Washer Combination Lever Set
Turn Signal / Headlight / Windshield Wiper/Washer Combination Switch and Lever Set
Notice how Windshield Wiper Arm is the first result because it contains the search parameters (which is simply "Windshield Wiper") and a follow-up word that begins with the letter A.
Anyway, here's my model:
class Pcdb::Part < CatalogsRecord
include PgSearch
self.table_name = "parts"
belongs_to :parts_description
pg_search_scope :search_for_parts, against: :part_terminology_name, using: { tsearch: { dictionary: "simple", normalization: 2 } }
end
And the relevant part of my controller:
Pcdb::Part.where('lower(parts.part_terminology_name) like ?', "%#{search}%").reorder("parts.part_terminology_name ASC")
In this particular instance, the search
variable is Windshield Wiper
.
Thanks in advance!
Upvotes: 0
Views: 446
Reputation: 147166
You could add a conditional to your ordering expression, checking whether the name started with the search term, and ordering those results first i.e. (as SQL)
ORDER BY
CASE WHEN parts.part_terminology_name LIKE 'Windshield Wiper%' THEN 0 ELSE 1 END,
parts.part_terminology_name
If you want to get more sophisticated about ordering, you could use regex to ensure that parts with the phrase followed by a word sorted before those with the phrase followed by a symbol (i.e. Windshield Wiper Arm
before Windshield Wiper / Washer Circuit Breaker
)
ORDER BY
CASE WHEN parts.part_terminology_name = 'Windshield Wiper' THEN 0 ELSE 1 END,
CASE WHEN parts.part_terminology_name ~ '^Windshield Wiper [a-z]' THEN 0 ELSE 1 END,
CASE WHEN parts.part_terminology_name LIKE 'Windshield Wiper%' THEN 0 ELSE 1 END,
parts.part_terminology_name
Upvotes: 1