#21 ✓resolved
Jess Martin

Search across multiple models

Reported by Jess Martin | November 3rd, 2008 @ 04:31 PM

Do you think it would be difficult to extend Searchlogic to search across multiple models at once? Or would you recommend switching to another search framework in order to solve this problem.

Essentially, we have two models in our system (documents and messages) that have the same columns except one model has a file attachment and the other does not. We'd like to have unified search across the two models. All we are interested in searching is the title field for each model.


Comments and changes to this ticket

  • Ben Johnson

    Ben Johnson November 3rd, 2008 @ 04:39 PM

    • State changed from “new” to “open”

    From the looks of it, it sounds pretty simple, but maybe I don't fully understand your problem. Why not just search both in your controller action? I do this on a recent site I developed: www.neco.com. Type "madison" in the search box. You will see I search both performers and venues in the same action. Here is the action for that search:

    @target = params[:target]
    @search_params = (params[:quick_search] || {}).dup
    @search_params.delete(:name_keywords) if @search_params[:name_keywords] == "Enter artist, team, or venue"
    if @target.blank? || @target == "performers"
      @performer_search = Performer.new_search(@search_params)
      @performers, @performers_count = @performer_search.all, @performer_search.count
    if @target.blank? || @target == "venues"
      @venue_search = Venue.new_search(@search_params)
      @venues, @venues_count = @venue_search.all, @venue_search.count

    Then in my view that renders the "performers" results I have the following:

    <%= remote_order_by_link :name, :search_obj => @performer_search, :params_scope => :quick_search, :params => {:target => "performers"} %>


    <%= remote_per_page_select :search_obj => @performer_search, :params_scope => :quick_search, :params => {:target => "performers"} %>


    <%= remote_page_links :search_obj => @performer_search, :params_scope => :quick_search, :params => {:target => "performers"} %>

    Hope that helps.

  • Jess Martin

    Jess Martin November 4th, 2008 @ 12:46 PM

    Hey Ben, Thanks for answering so quickly.

    The example you provide solves half of our problem. We can definitely search both of the models from a single form. However, is there any way to merge the results together into a single result set while still maintaining Searchlogic's pagination abilities? In our case, I think it makes sense for the search results (both messages and documents) to be displayed to the user in the same results block.

    Also, your solution technically does two searches. Ideally we'd like to do something like the following:

    select * from documents, messages where documents.title LIKE '%asdf%' OR messages.title LIKE '%asdf%';

    Thanks for your help!

  • Ben Johnson

    Ben Johnson November 4th, 2008 @ 12:51 PM

    Hey Jess,

    Yeah I see what you're saying. To my knowledge, the problem is that you can't even accomplish that with ActiveRecord alone, unless you write the entire query youself. Even then I'm not sure what ActiveRecord would do to be honest. Can you accomplish this with ActiveRecord?

  • Jess Martin

    Jess Martin November 4th, 2008 @ 04:59 PM

    Ben, Good point. You can't really do this effectively in ActiveRecord. You can do

    Document.find_by_sql("select * from documents, messages where documents.title LIKE '%asdf%' OR messages.title LIKE '%asdf%'")

    and ActiveRecord will try to "pretend" that everything that is returned from that query is a Document, when actually some of the things are Messages.

    I ended up pushing your solution (splitting the results into two sets) over to our client to see if they accept that UI. Hopefully that will work.

    Thanks again for your help.

  • Ben Johnson

    Ben Johnson November 4th, 2008 @ 05:38 PM

    • State changed from “open” to “resolved”

    No problem. I see what ActiveRecord is doing, but that seems wrong to me, because the documents arent really documents. If you do something like:

    => true

    And it actually isnt a document, that would just mess things up. I would stay away from doing that.

    Your other option is to put all of the results into a single array and sort them manually:

    [].sort! { |a,b| a <=> b }

    This is actually highly inefficient, but it wouldnt be too bad for small arrays. Hope that helps.

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

Provides common named scopes and object based searching.

People watching this ticket