#1 hold
Peer Allan

Feature Request: Indexing associations

Reported by Peer Allan | June 3rd, 2009 @ 04:06 PM | in Feature Requests

Checking out sunspot and sunspot_rails, but could not find a way to index associated models in the Rails gem.

E.g

searchable do
  text :first_name
  include :address => [:city, :state, :zip]
end

Do you have any plans to tackle something like this?

Peer

Comments and changes to this ticket

  • mat

    mat June 3rd, 2009 @ 06:34 PM

    • Milestone set to Feature Requests

    As far as simply indexing attributes of associated models, a virtual field is currently the easiest way to do that:

    searchable do
      text :first_name
      string(:address_city) { address.city }
      string(:address_state) { address.state }
      string(:address_zip) { address.zip }
    end
    

    Not quite as succinct as the example you give, but there does at the least need to be a way to specify the field type. Do you see a big advantage in exposing an interface explicitly geared toward indexing associated objects?

  • Peer Allan

    Peer Allan June 4th, 2009 @ 02:55 PM

    That makes sense for a has_one or belongs_to, but what about has_many? The specific situation is that when we search for a customer we want to search all of there addresses. Our users want to do searches like "john smith texas" and get John Smith to show up even if only his third alternate address is in Texas. Does that make sense?

    As for the being explicit I will agree that I don't see a real requirement for it. The code about was just an example. In the context of Rails and ActiveRecord models I like it because it matches the conventions and would be instantly clear to a Rails developer.

    Peer

  • mat

    mat June 4th, 2009 @ 03:04 PM

    • State changed from “new” to “hold”

    Makes perfect sense. For typed fields, the pattern would be:

    class User
      searchable do
        string :address_states, :multiple => true do
          addresses.map { |address| address.state }
        end
      end
    end
    

    For fulltext fields, it's a little hackier:

    class User
      searchable do
        text :address_states do
          addresses.map { |address| address.state } * ' '
        end
      end
    end
    

    That's because the text type currently isn't configurable to allow multiple entries. That can, should, and will be fixed in the next release. I'm not sure whether the above method would have any effect on relevance calculations vs. indexing multiple separate values for the field.

    I'm a bit reluctant to add Rails-specific functionality inside the DSL, because at the moment Sunspot::Rails just passes the DSL block to Sunspot; doing something Rails-specific would require creating a separate DSL class in Sunspot::Rails that then delegates to the Sunspot DSL. That would add a layer of complexity to Sunspot::Rails which I'd prefer to avoid; I like keeping it just a very thin wrapper. However, if there's more demand for it I'll certainly revisit the issue.

  • Peer Allan

    Peer Allan June 4th, 2009 @ 03:32 PM

    I totally agree. No use adding complication if you don't have to!

  • Magnus Bergmark

    Magnus Bergmark November 11th, 2009 @ 05:23 AM

    One approach that might work is to just have it delegated already through the standard Rails conventions:

    class User
      delegate :city, :state, :zip, :to => :address
      searchable do
        string :address_city
        string :address_state
        string :address_zip
      end
    end
    

    If the Sunspot setup DSL should support this without changing the models beforehand, a similar pattern could be used. Here's an examples for how it could look like:

    class User
      searchable do
        # :prefix is optional
        delegate :string => [:city, :state, :zip], :to => :address, :prefix => "address_"
      end
    end
    

    Otherwise, there could be a shortcut for referring to "nested" methods:

    class User
      searchable do

    string :"address.city"  # Will be saved as "address_city", but send(:address).send(:city)
    string :"address.state"
    string :"address.zip"
    
    
    
    
    end end

    Personally, I do not like it since we use magic characters in the field name, but if dots are not allowed in field names (which might be true), it is a valid solution.

    Both of the solutions here only work for single values with a depth of 1, but if you actually need multiple values or nested in more levels I think you should just whip out the block anyway. It would be hard to generalize that for everyone and still keep it cleaner than just adding a small block to the method call.

  • Magnus Bergmark

    Magnus Bergmark November 11th, 2009 @ 05:25 AM

    My code got messed up for some reason. I'll try to post it again (I wish I could preview and/or edit comments here)

    class User
      searchable do
        # Will be saved as "address_city", but send(:address).send(:city)
        string :"address.city"
        string :"address.state"
        string :"address.zip"
      end
    end
    

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 ยป

Awesome Solr interaction for Ruby

Pages