Apr 18, 2009

Named Scopes and Thinking Sphinx

I'm really not a fan of the Thinking Sphinx conditions syntax. It's different than what I'm used to using in ActiveRecord and has caused me some problems with dates and such. Instead I use named scopes whenever I can. For example, in Railfood, a site for locomotive parts, I use a named scope to show only products that are in stock. That causes some issues, not only because of all the nil records but because the default number of results returned is 20.

Note that this article is no longer that useful. Instead of named scopes please look at sphinx scopes. Article coming soon.

For example:
@p =Product.current.search("injector").size 

=> 20

@p =Product.current.search("123").size 

=> 20

One of the first gotchas (covered here too) is that if you actually inspect that array you'll see that it's filled with nil.

[nil, nil, nil, nil nil,nil, nil, nil, nil nil,nil, nil, nil, nil nil,nil, nil, nil, nil nil,]

To get around it, call the compact method on the array:

@p =Product.current.search("injector").compact.size 

=> 0

The other gotcha here is that if you actually have 20000 records that match "injector" but only 1 of them is current, you'll get zero results. To work around that you need to increase the maximum amount of results per page:

@p =Product.current.search("injector", :per_page => 20000).compact.size 

=> 1

But what about pagination? Thinking Sphinx does give us this, but the fact that both the methods are called :per_page kind of screws things up. To work around this, just call paginate on your results:

@p =Product.current.search("injector",
:per_page => 20000).paginate(:per_page => 8, :page => params[:page])

And that should do it. Of course, depending on how many results you have you may need to up the initial per_page from 20000 to something larger. This isn't ideal in my humble opinion, but it works for the moment. Other suggestions are welcome!

While we're on the subject of Thinking Sphinx, be sure to set :enable_star => 1 in your index block if you want to use wildcards in your searches.

No comments:

Post a Comment