1

I'm trying to implement search over tags as part of a Texticle search. Since texticle doesn't search over multiple tables from the same model, I ended up creating a new model called PostSearch, following Texticle's suggestion about System-Wide Searching

class PostSearch < ActiveRecord::Base

  # We want to reference various models
  belongs_to :searchable, :polymorphic => true
  # Wish we could eliminate n + 1 query problems,
  # but we can't include polymorphic models when
  # using scopes to search in Rails 3
  # default_scope :include => :searchable

  # Search.new('query') to search for 'query'
  # across searchable models
  def self.new(query)
    debugger
    query = query.to_s
    return [] if query.empty?
    self.search(query).map!(&:searchable)
    #self.search(query) <-- this works, not sure why I shouldn't use it.
  end

  # Search records are never modified
  def readonly?; true; end

  # Our view doesn't have primary keys, so we need
  # to be explicit about how to tell different search
  # results apart; without this, we can't use :include
  # to avoid n + 1 query problems
  def hash
   id.hash
  end

  def eql?(result)
    id == result.id
  end

end

In my Postgres DB I created a view like this:

  CREATE VIEW post_searches AS
  SELECT posts.id, posts.name, string_agg(tags.name, ', ') AS tags
    FROM posts
      LEFT JOIN taggings ON taggings.taggable_id = posts.id 
        LEFT JOIN tags ON taggings.tag_id = tags.id 
  GROUP BY posts.id;

This allows me to get posts like this:

SELECT * FROM post_searches
id | name | tags
1    Intro  introduction, funny, nice

So it seems like that should all be fine. Unfortunately calling PostSearch.new("funny") returns [nil] (NOT []). Looking through the Texticle source code, it seems like this line in the PostSearch.new

self.search(query).map!(&:searchable)

maps the fields using some sort of searchable_columns method and does it ?incorrectly? and results in a nil.

On a different note, the tags field doesn't get searched in the texticle SQL query unless I cast it from a text type to a varchar type.

So, in summary: Why does the object get mapped to nil when it is found?

AND

Why does texticle ignore my tags field unless it is varchar?

you786
  • 3,659
  • 5
  • 48
  • 74

1 Answers1

1

Texticle maps objects to nil instead of nothing so that you can check for nil? - it's a safeguard against erroring out checking against non-existent items. It might be worth asking tenderlove himself as to exactly why he did it that way.

I'm not completely positive as to why Texticle ignores non-varchars, but it looks like it's a performance safeguard so that Postgres does not do full table scans (under the section Creating Indexes for Super Speed):

You will need to add an index for every text/string column you query against, or else Postgresql will revert to a full table scan instead of using the indexes.

acconrad
  • 3,201
  • 1
  • 22
  • 31
  • Hmm... but I can't have an index on a view can I? Also, the reasoning behind making it nil makes sense I suppose, but do you have any idea why it actually is mapped to nil? – you786 Apr 26 '12 at 20:35
  • Views are temporary tables so you cannot index them directly, but you CAN index the underlying table(s) that you are drawing your view from. I don't know exactly why it's mapped to `nil` so again, I would suggest you reach out to texticle's creator to investigate the "why". – acconrad Apr 27 '12 at 15:22