pg_search
pg_search copied to clipboard
Multisearch not working on a model that uses UUID for a primary key
I have a model:
CREATE TABLE businesses (
id uuid DEFAULT uuid_generate_v4() NOT NULL,
slug character varying(255),
name character varying(255),
phone_number character varying(255),
website character varying(255),
description text,
latitude numeric(9,6),
longitude numeric(9,6)
);
And am able to do a single-model search with it:
pg_search_scope :search_by_properties, :against => [:website, :name, :description]
But when I try to do a multi-search using the following:
multisearchable :against => [:website, :name, :description]
I get errors on model creation. Attached is a log of where the actual object creation fails:
?> b = Business.create(name: "Foo")
(0.2ms) BEGIN
SQL (7.2ms) INSERT INTO "businesses" ("created_at", "name", "updated_at") VALUES ($1, $2, $3) RETURNING "id" [["created_at", Tue, 19 Nov 2013 15:42:00 CST -06:00], ["name", "Foo"], ["updated_at", Tue, 19 Nov 2013 15:42:00 CST -06:00]]
PgSearch::Document Load (0.9ms) SELECT "pg_search_documents".* FROM "pg_search_documents" WHERE "pg_search_documents"."searchable_id" = $1 AND "pg_search_documents"."searchable_type" = $2 ORDER BY "pg_search_documents"."id" ASC LIMIT 1 [["searchable_id", "24c17e11-c6e6-4133-af42-36ae1b7f6651"], ["searchable_type", "Business"]]
Business Load (1.1ms) SELECT "businesses".* FROM "businesses" WHERE "businesses"."id" = $1 ORDER BY "businesses"."id" ASC LIMIT 1 [["id", 24]]
PG::InvalidTextRepresentation: ERROR: invalid input syntax for uuid: "24"
: SELECT "businesses".* FROM "businesses" WHERE "businesses"."id" = $1 ORDER BY "businesses"."id" ASC LIMIT 1
(0.2ms) ROLLBACK
ActiveRecord::StatementInvalid: PG::InvalidTextRepresentation: ERROR: invalid input syntax for uuid: "24"
: SELECT "businesses".* FROM "businesses" WHERE "businesses"."id" = $1 ORDER BY "businesses"."id" ASC LIMIT 1
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:786:in `get_last_result'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:786:in `exec_cache'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:139:in `block in exec_query'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:435:in `block in log'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activesupport-4.0.1/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract_adapter.rb:430:in `log'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/postgresql_adapter.rb:891:in `select'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:24:in `select_all'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/querying.rb:36:in `find_by_sql'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/relation.rb:585:in `exec_queries'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/association_relation.rb:15:in `exec_queries'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/relation.rb:471:in `load'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/relation.rb:220:in `to_a'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/relation/finder_methods.rb:325:in `find_first'
... 35 levels...
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/transactions.rb:326:in `block in with_transaction_returning_status'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `block in transaction'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:210:in `within_new_transaction'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/connection_adapters/abstract/database_statements.rb:202:in `transaction'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/transactions.rb:209:in `transaction'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/transactions.rb:323:in `with_transaction_returning_status'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/transactions.rb:270:in `block in save'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/transactions.rb:281:in `rollback_active_record_state!'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/transactions.rb:269:in `save'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/activerecord-4.0.1/lib/active_record/persistence.rb:37:in `create'
from (irb):5
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.1/lib/rails/commands/console.rb:90:in `start'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.1/lib/rails/commands/console.rb:9:in `start'
from /Users/litch/.rvm/gems/ruby-2.0.0-p247/gems/railties-4.0.1/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'
The pg_search_documents
table uses the searchable_type
and searchable_id
columns as a polymorphic foreign key back to the original record. But in your database, those types are mismatched.
So I think you would either commit to using UUIDs for all searchable types, and migrate the searchable_id
column to be of type uuid
, or perhaps you could get away with using a string type instead. You'd need to be careful that the polymorphic association still works for all your various searchable models.
Let me know what you find out. This is an interesting problem, and a reasonable use case I'd like to be able to support.
Oops, misclicked, didn't mean to close the issue.
Thanks! Yes, I think that sounds good. I had just taken a quick stab at it, but if I decide to implement it (which I'm like 80% sure I will), I'll send it upstream.
@litch please close this issue if you have found the solution. Feel free to share your final solution what worked for you, so others could learn. Thanks.
@giedriusr I don't want this issue closed if it represents a real problem in the gem. This is supposed to work without a workaround.
I think most people who are using uuids for keys are probably using them everywhere, it would be nice if there were just a note on the readme about needing to change the generated migration if that is the case.
For me I simply needed to change the t.belongs_to :searchable...
line in the migration to include :type => :uuid
before running it and was set.
Seems to me it would be safer to have the searchable_id
column be varchar
and just use typecasting on index? I definitely don't have integers nor UUIDs for my records (they vary, naturally), but varchar
is able to represent both.