Web Images Videos Maps News Shopping Gmail more »
Recently Visited Groups | Help | Sign in
Google Groups Home
Message from discussion Advanced faceting Howto
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
 
From:
To:
Cc:
Followup To:
Add Cc | Add Followup-to | Edit Subject
Subject:
Validation:
For verification purposes please type the characters you see in the picture below or the numbers you hear by clicking the accessibility icon. Listen and type the numbers you hear
 
Ward  
View profile  
 More options Jun 20 2008, 6:54 am
From: Ward <w.bek...@equanimity.nl>
Date: Fri, 20 Jun 2008 03:54:36 -0700 (PDT)
Local: Fri, Jun 20 2008 6:54 am
Subject: Advanced faceting Howto
Hi,

I needed facetings (also called slicing or drill-down, example on the
left here: http://www.newegg.com/Store/SubCategory.aspx?SubCategory=14&name=Inte...)
for my current project, and managed to implement this using thinking
sphinx. I took me some time to get it working OK, so i'm sharing it
here for the next guy/girl ;-).

Tom Davies (you rule!) added this monkeypatch (put at the end of
environment.rb for example) to query for multiple facets

require 'thinking_sphinx'
module ThinkingSphinx
  class Search
    class << self
      # Add facet support
      def facets(query, attrs, options={})
        options.merge!({:group_function => :attr, :group_clauses =>
"@count desc"})
        attrs = [attrs] unless attrs.is_a? Array
        attr_facets = {}
        attrs.each do |attr|
          options[:group_by]=attr
          results, client = search_results(query, options)
          facets = {}
          results[:matches].each {|e| facets[e[:attributes]
['@groupby']]=e[:attributes]['@count']}
          attr_facets[attr] = facets
        end
        attr_facets
      end
    end
  end
end

Next I specified in my model the attributes that are used in the
faceting (mysql database):

has "(SELECT GROUP_CONCAT(match_crit.id) from vacature v join
match_set on (v.match_id=match_set.match_id) join match_crit on
(match_set.match_crit_id=match_crit.id) where match_crit.soort =
'region' and v.id = vacature.id)", :as => 'region', :type => :multi

Some explanations about the sql: it returns a string of comma
seperated id's of the values of the attribute 'region'. the :type
=> :multi tells sphinx that it should treat the string as an array of
values. I needed customed sql, because the database scheme it a bit
more complex. It's important to use the correct syntax for "v.id =
vacature.id". vacature.id is the field that is used in the where
clause of the query used by sphinx for loading the field values of a
'vacature' record. The query above is used as a subselect in that
query. The full query is something like this (simplified) "SELECT *,
(SELECT GROUP_CONCAT FROM Vacature v WHERE v.id = Vacature.id) as
region  WHERE Vacature.id = x"

You now can start with the indexing. In the Rake task you should see a
line that signals it's creating an index voor the MVA (multi-value
attributes) which are used for creating the facets.

When done indexing, you can query for the facet values of 'region' for
a specific query, in this example we are looking for a carpenter job
offers:

result = ThinkingSphinx::Search.facets("carpenter", ['region'])

the result hash contents if for example:  {'region' => {1 => 10, 2 =>
30}}. This means that there are 10 job offers found for carpenters in
region 1, and 30 in region two. The important think to note here is
that a single job offer can be in multiple regions. So the total
results of the query doesn't have to be 10 + 30 = 40, but can be as
low as 30.

Let's say the user want's to see all carpenter job offers of region 1,
the query becomes (this is helpfull when drilling down if you have
more attributes than region alone):

result = ThinkingSphinx::Search.facets("carpenter", ['region'], :with
=> { 'region'  => 1"})

Propably obvious, but to get the actual job offers, you need to
execute

Model.search("carpenter", :with => { 'region'  => 1"})

Have fun!,

Ward


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2009 Google