Unneeded activerecord instantiating when usings facet search

30 views
Skip to first unread message

Ward

unread,
Sep 3, 2009, 9:04:01 AM9/3/09
to Thinking Sphinx
Hi,

I noticed that the current implementation of faceting is instantiating
active record instances without a real need.

For example, when getting the facets for number of rooms when
searching for sunny houses:

House.facets("sunny", :facets => [:rooms]) # results in { :rooms =>
{ 3 => 66, 2 => 33 }}

(So there are 66 3-room houses and 33 2-room houses)

Unfortunately, per facet "result" there is also an House record
fetched from the DB. For attributes that have a lot of different
values, this get's ugly pretty fast, and totally unneeded.

For my project i've created a quick monkey patch that solves this.
Basically i've used the ids_only search, to make sure not instances
are created when doing a search. Because this gives a different search
result, I've changed the way the facet result hash is composed. I
don't have time to fix the specs yet, I plan to do that later.

Enjoy!,

Ward


### Warning: monkey patch ahead ###############

module ThinkingSphinx
class FacetSearch

def facet_search_options
config = ThinkingSphinx::Configuration.instance
max = config.configuration.searchd.max_matches || 1000

options.merge(
:ids_only => true, #otherwise activerecord instances are
created, we don't need those
:group_function => :attr,
:limit => max,
:max_matches => max,
:page => 1
)
end

def add_from_results(facet, results)
results = results.results

name = ThinkingSphinx::Facet.name_for(facet)
self[name] ||= {}

results[:matches].each do |match|

facet_value = match[:attributes][name.to_s]
facet_count = match[:attributes]["@count"]

self[name][facet_value] ||= 0
self[name][facet_value] += facet_count
end
end

end
end

Pat Allan

unread,
Sep 3, 2009, 9:26:22 AM9/3/09
to thinkin...@googlegroups.com
Hi Ward

In some cases, these objects are needed - when there are string facets
based on fields. Because we can't store the values as strings (CRC'd
to integers, which can't be reversed as far as I know), we need the
objects to translate the values back.

Ideally, TS should be smart enough, and use :ids_only => true for
facets that don't need the objects. If you could make your patch smart
enough to handle these situations (with specs too, if possible),
that'd be fantastic. Otherwise, feel free to create an issue on
GitHub, and I'll try to get it sorted out at some point.

Cheers

--
Pat

Ward (TTY)

unread,
Sep 3, 2009, 9:47:28 AM9/3/09
to Thinking Sphinx
Hi Pat,

Ah yes, i understand now why it is needed in some cases. Thinking of
it, the string attribute face case can also be optimized by using
"ids_only => true". In that case, the add_from_results method can do a
"select house_type from houses where id in {sphinx_internal_id's}"
using the sphinx_internal_id's of the matches. In that way only the
values needed would be fetched.

I'll work on a patch later. I'll let you know when that's ready for
review.

Bye!

Ward
Reply all
Reply to author
Forward
0 new messages