From 1a56c88af1f58c8f4b5d11feeb41f9303c022354 Mon Sep 17 00:00:00 2001 From: Ben Hadley-Evans Date: Mon, 18 May 2015 17:19:43 +0100 Subject: [PATCH 1/2] Avoid casting a tsvector column to text and back again. When you have a tsvector column but want to search against both it and other text columns (without having to deal with triggers) the :tsvector_column option is no use as it causes everything in :against to be ignored. Also since a column's type is available I don't see why the need to specify something as a tsvector column. This change allows you to simply pass column names to :against, and if any of those are tsvectors then they will be used directly, otherwise they will be converted to tsvectors as before. My data set is over 900 records and as well as the document I search 4 additional small text fields, also there is an postgres gin index being used. On a query that matched just 4 results the speed improved from 40ms to 3ms. And on a query that matched 397 results the speed improved from over 3000ms to 60ms. --- lib/pg_search/configuration/column.rb | 15 ++++++++++++++- lib/pg_search/features/tsearch.rb | 12 ++++++++---- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/lib/pg_search/configuration/column.rb b/lib/pg_search/configuration/column.rb index 4c4cf99e..f3c95203 100644 --- a/lib/pg_search/configuration/column.rb +++ b/lib/pg_search/configuration/column.rb @@ -18,7 +18,16 @@ def full_name end def to_sql - "coalesce(#{expression}::text, '')" + coalesce("#{expression}::text") + end + + def to_sql_no_cast + coalesce(expression) + end + + def tsvector? + psql_column = @model.columns_hash[name] + psql_column && psql_column.type.eql?(:tsvector) end private @@ -34,6 +43,10 @@ def column_name def expression full_name end + + def coalesce(value) + "coalesce(#{value}, '')" + end end end end diff --git a/lib/pg_search/features/tsearch.rb b/lib/pg_search/features/tsearch.rb index ddec16bf..cef70bc2 100644 --- a/lib/pg_search/features/tsearch.rb +++ b/lib/pg_search/features/tsearch.rb @@ -122,10 +122,14 @@ def columns_to_use end def column_to_tsvector(search_column) - tsvector = Arel::Nodes::NamedFunction.new( - "to_tsvector", - [dictionary, Arel.sql(normalize(search_column.to_sql))] - ).to_sql + if search_column.tsvector? + tsvector = Arel.sql(normalize(search_column.to_sql_no_cast)) + else + tsvector = Arel::Nodes::NamedFunction.new( + "to_tsvector", + [dictionary, Arel.sql(normalize(search_column.to_sql))] + ).to_sql + end if search_column.weight.nil? tsvector From 17fed35ab50ee905c02961c6f8d0d935fce530cc Mon Sep 17 00:00:00 2001 From: Ben Hadley-Evans Date: Mon, 24 Aug 2015 13:54:57 +0100 Subject: [PATCH 2/2] Improve Metrics/AbcSize of TSearch#column_to_tsvector. --- lib/pg_search/features/tsearch.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/pg_search/features/tsearch.rb b/lib/pg_search/features/tsearch.rb index cef70bc2..a1235984 100644 --- a/lib/pg_search/features/tsearch.rb +++ b/lib/pg_search/features/tsearch.rb @@ -131,11 +131,11 @@ def column_to_tsvector(search_column) ).to_sql end - if search_column.weight.nil? - tsvector - else - "setweight(#{tsvector}, #{connection.quote(search_column.weight)})" + if search_column.weight + tsvector = "setweight(#{tsvector}, #{connection.quote(search_column.weight)})" end + + tsvector end end end