When Ultrasphinx is used with polymorphic associations…

Lets first consider simple has_many and belongs_to associations as:

Now if you wish to index the title of associated article with comment for searching, you just need to add ” is_indexed :fields => :body, :include => [{ :association_name => ‘article’, :field => ‘title’, :as=> ‘article_title’}] ”

So, your comment model will look like:

Setup ultrasphinx by issuing:

Now at rails console try:

Simple, we have article and comment models with has_many belongs_to associations. Comments are indexed with their associated article title. So it can return comments if query matches with article’s titles.

Now, consider a case when we wish to change comment model to make it polymorphic. In that case our models will be look like:

Check at rails if associations are working fine:

Now, the point is to index article title with comments. Here we can get associated article using ‘commentable’ i.e. comment.commentable.

So, change ultrasphinx is_indexed code in comment model accordingly:

Note that we have changed associan_name to ‘commentable’.
Next, when we reconfigure ultrasphinx using ” rake ultrasphinx:bootstrap”(since we have changed db schema), it starts throwing errors:

After spending some time on research, I was able to make it work by making some changes in comment model:

Lets check it on rails console:

In such cases we need to define class_name and association_sql in is_indexed statement instead of association_name.

Hope it helps…

When Ultrasphinx is used with STI…

Hi Guys, it has been a long time since I last posted. I had worked on several things since then, and have couple of posts pending/draft. One of those posts is related to Ultrasphinx, when it is used with STI models.

For those who are new to Ultrasphinx: Ultrasphinx is a rails plugin and client to the Sphinx(full text search engine) written by Evan Weaver. More about Ultrasphinx here.

Lets get into the situation. Consider a STI case where we are using ultrasphinx to index several fields:

Now assume we have following data in posts table:
and now in application root:

By this point we have created sphinx configuration file, indexed all records from ultrasphinx models and started sphinx search daemon.

Now open script/console and create and fire a query to find some articles:

Here when you run the query you get an exception, because it is trying to find an article with id 5, which actually a story type not article. So why it is trying to find such article?

Now have a look into config/ultrasphinx/development.conf file. Under section “source articles_main” you’ll get “SELECT (posts.id * 3 + 0) AS id, ‘’ AS article_title, posts.body AS body, ‘Article’ AS class, 0 AS class_id, posts.title AS title FROM posts WHERE posts.id >= $start AND posts.id <= $end GROUP BY posts.id" Which is a SQL to get record to index. If you check it carefully you'll findout that it should select all articles record to index but unfortunately it is selecting all records from table and considering them as articles. To fix it you need to modify this query and add "posts.type = 'Article'" in where condition. So the query should be "SELECT (posts.id * 3 + 0) AS id, '' AS article_title, posts.body AS body, 'Article' AS class, 0 AS class_id, posts.title AS title FROM posts WHERE (posts.type = 'Article') and posts.id >= $start AND posts.id <= $end GROUP BY posts.id" But still there is a problem. If you do this manually you have to do it again and again whenever you issue "rake ultrasphinx:configure" because this configuration file will be overwritten. Better option is to add conditions in models as is_indexed options like:

and it worked fine.

Manik gave me an idea to write a patch for ultrasphinx to add such conditions automatically in case of STI. So may be another post related to ultrasphinx will be soon ;-)

Update: Here is the patch Git patch: Fix STI Issue. After applying this patch you need not to add conditions explicitly for such case. It will automatically check and add conditions for STI.